home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianSockets.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  93KB  |  3,590 lines

  1. /*ScianSockets.c
  2.   Eric Pepke
  3.   April 25, 1990
  4.   Stuff for socket interface in Scian
  5.  
  6.   Taken over by John R. Murray
  7.   June 29, 1992
  8. */
  9.  
  10. #include "Scian.h"
  11. #include "ScianTypes.h"
  12. #include "ScianSockets.h"
  13. #include "ScianArrays.h"
  14. #include "ScianLists.h"
  15. #include "ScianControls.h"
  16. #include "ScianButtons.h"
  17. #include "ScianNetDaemon.h"
  18. #include "ScianWindows.h"
  19. #include "ScianObjWindows.h"
  20. #include "ScianVisWindows.h"
  21. #include "ScianTextBoxes.h"
  22. #include "ScianDialogs.h"
  23. #include "ScianIDs.h"
  24. #include "ScianScripts.h"
  25. #include "ScianErrors.h"
  26. #include "ScianColors.h"
  27. #include "ScianDialogs.h"
  28. #include "ScianEvents.h"
  29. #include "ScianTimers.h"
  30. #include "ScianStyle.h"
  31. #include "ScianDatasets.h"
  32. #include "ScianDraw.h"
  33. #include "ScianIcons.h"
  34. #include "ScianObjFunctions.h"
  35. #include "ScianGarbageMan.h"
  36. #include "ScianNetObjects.h"
  37. #include "ScianHelp.h"
  38.  
  39. /* temporary? */
  40. #include <errno.h>
  41.  
  42. /* NEWSTYLEUPDATES enables auto-transmission of netids and/or objects after an UPDATEVAR */
  43. #define NEWSTYLEUPDATES
  44. /* HAK */
  45.  
  46. /* #define MESGSTATS */
  47. /*Line for mkmk*/
  48. /*$cc -I/usr/include/bsd ScianSockets.c -c $(CFLAGS)
  49. */
  50.  
  51. /*Public objects*/
  52. ObjPtr advertiseableClass = NULLOBJ;
  53. ObjPtr allAdvertised = NULLOBJ;    /*All objects advertised from
  54.                       this process (list)*/
  55.  
  56. /* this should probably move to Scian.h and ScianMain.c */
  57. int libRunning = 0;
  58.  
  59. #ifdef SOCKETS
  60.  
  61. #define SHORT_TIMEOUT    5.0        /*Short timeout on socket*/
  62. #define LONG_TIMEOUT    10.0        /*Long timeout*/    
  63.  
  64. /*Kinds of connection*/
  65. #define CK_REMOTE_DAEMON    1    /*Connection to a remote network daemon*/
  66. #define CK_LOCAL_DAEMON        2    /*Connection to a local daemon*/
  67. #define CK_LISTENING_SCIAN    3    /*Listening connection on a local SciAn*/
  68. #define CK_REMOTE_SCIAN        4    /*Connection to a remote SciAn (not implemented)*/
  69. #define CK_LOCAL_SCIAN        5    /*Connection from a local SciAn (not implemented)*/
  70.  
  71. /*Values for connection state*/
  72. #define CS_NAME_ONLY        0    /*Just have the name of target, nothing else*/
  73. #define CS_WAIT_FOR_VERSION    1    /*Waiting for a version reply*/
  74. #define CS_MORIBUND        2    /*Moribund connection, ready to die*/
  75. #define CS_LIMBO        3    /*Connection in limbo, doing nothing*/
  76. #define CS_IDLING        4    /*Idling a connection.*/
  77. #define CS_FILL_CMD        5    /*Fill a command*/
  78. #define CS_WAIT_FOR_CMD_END    6    /*Wait for the end of a command*/
  79. #define CS_READ_PROC_NAME    7    /*Read a process name*/
  80. #define CS_NOT_LISTENING    8    /*Accepting socket, not listening yet*/
  81. #define CS_LISTENING        9    /*Accepting socket, listening*/
  82. #define CS_WAIT_FOR_PASSWORD    10    /*Of a recieving socket, wait for a password*/
  83. #define CS_READ_OBJECT        11    /*Read an Object */
  84. #define CS_READ_NUMBER_ONE    12    /*Read a number*/
  85. #define CS_READ_NUMBER_TWO    13    /*Read the second number*/
  86. #define CS_READ_NUMBER_THREE    14    /*Read the third number*/
  87. #define CS_READ_NUMBER_FOUR    15    /*Read the fourth number*/
  88.  
  89. /*Local variables*/
  90. static char *stateName[] = 
  91.     {
  92.         "name only",
  93.         "waiting for version",
  94.         "moribund",
  95.         "limbo",
  96.         "idle connection",
  97.         "fill cmd",
  98.         "wait for cmd end",
  99.         "read proc name",
  100.         "not listening",
  101.         "listening",
  102.         "wait for password",
  103.         "read object",
  104.         "read number one",
  105.         "read number two",
  106.         "read number three",
  107.         "read number four"
  108.     };
  109. static char *lastComputer = 0;        /*Address of last computer to be dialed*/
  110. static int lastSocketTried = ND_BASE_SOCKET_NUMBER;
  111.                     /*Last process # tried*/
  112. static ObjPtr connectionClass;        /*Class of connections*/
  113. static ObjPtr processClass;        /*Class of processes*/
  114. static ObjPtr allConnections;        /*List of all the connections*/
  115. static ObjPtr processIcon;            /*Icon that represents the process*/
  116. static ObjPtr publicationConnection;    /*Connection for publications*/
  117.  
  118. /*Local prototypes*/
  119. #ifdef PROTO
  120. static ObjPtr NewConnection(char *, int);
  121. static void SetConnectionState(ObjPtr connection, int state);
  122. static int GetConnectionState(ObjPtr connection);
  123. static void DeleteProcess(ObjPtr connection, int procNum);
  124. static ObjPtr NewProcess(ObjPtr connection, char *procName, int procSocket);
  125. static int SocketPort(void);
  126. #else
  127. static ObjPtr NewConnection();
  128. static void SetConnectionState();
  129. static int GetConnectionState();
  130. static void DeleteProcess();
  131. static ObjPtr NewProcess();
  132. static int SocketPort();
  133. #endif
  134.  
  135. /*Local methods*/
  136. static ObjPtr ConnectToComputerAgain();
  137. static ObjPtr ContinueWaiting();
  138. static ObjPtr ShowConnectionControls();
  139. static ObjPtr ConnectToProcess();
  140.  
  141. int writen(fd, cptr, nbytes)
  142. int fd;
  143. char *cptr;
  144. long nbytes;
  145. {
  146.     int nleft, nwritten;
  147.  
  148.     nleft = nbytes;
  149.     while (nleft > 0)
  150.     {
  151.     nwritten = write(fd, cptr, nleft);
  152.     if (nwritten < 0)
  153.     {
  154.         if (errno != EWOULDBLOCK && errno != EAGAIN)
  155.         {
  156.         perror("writen");
  157.         return;
  158.         }
  159.     }
  160.     else
  161.     {
  162.         nleft -= nwritten;
  163.         cptr += nwritten;
  164.     }
  165.     }
  166. }
  167.  
  168. int readn(sock, cptr, num)
  169. int sock;
  170. char *cptr;
  171. long num;
  172. {
  173.     double lastData;
  174.     long oldnum;
  175.     int olderrno = 0;
  176.     int notTimeOut = 1;
  177.  
  178.     oldnum = num;
  179.     lastData = WallClock();
  180.     while(num > 0 && (notTimeOut = lastData + JOHNSTIMEOUT > WallClock()))
  181.     {
  182.     long tmp;
  183.  
  184.     tmp = read(sock, cptr, num);
  185.     if (tmp > 0)
  186.     {
  187.         num -= tmp;
  188.         cptr += tmp;
  189.         lastData = WallClock();
  190.     }
  191.     if (tmp < 0 && olderrno != errno)
  192.     {
  193.         if (errno != EWOULDBLOCK && errno != EAGAIN)
  194.         {
  195.         perror("readn");
  196.         }
  197.         olderrno = errno;
  198.     }
  199.     }
  200.     if (!notTimeOut)
  201.     ReportError("readn", "timeout");
  202.  
  203.     return 0;
  204. }
  205.  
  206. #ifdef PROTO
  207. static int SocketPort(void)
  208. #else
  209. static int SocketPort()
  210. #endif
  211. /*Return a socket port which may or may not work*/
  212. {
  213.     return lastSocketTried++;
  214. }
  215.  
  216. static ObjPtr ConnectToComputerAgain(dummy, whichButton)
  217. ObjPtr dummy;
  218. int whichButton;
  219. /*Asks for a connect again depending on whichButton*/
  220. {
  221.     if (whichButton == 1) DoConnectToComputer();
  222.     return ObjTrue;
  223. }
  224.  
  225. static ObjPtr ContinueWaiting(connection, whichButton)
  226. ObjPtr connection;
  227. int whichButton;
  228. /*Has a connection continue waiting or not*/
  229. {
  230.     if (whichButton == 1)
  231.     {
  232.     /*Continue trying*/
  233.  
  234.     /*Set the state*/
  235.     SetVar(connection, CONNECTIONSTATE, 
  236.         GetVar(connection, OLDCONNSTATE));
  237.  
  238.     /*Set a timeout*/
  239.     SetTimeout(connection, TIMEOUT, WallClock() + LONG_TIMEOUT);
  240.     }
  241.     else
  242.     {
  243.     /*Set the state*/
  244.     SetConnectionState(connection, CS_MORIBUND);
  245.     }
  246.     return ObjTrue;
  247. }
  248.  
  249. #ifdef PROTO
  250. static void SetConnectionState(ObjPtr connection, int state)
  251. #else
  252. static void SetConnectionState(connection, state)
  253. ObjPtr connection;
  254. int state;
  255. #endif
  256. /*Changes the state of connection to connection*/
  257. {
  258.     ObjPtr oldState;
  259.  
  260.     /*Get the old state*/
  261.     oldState = GetVar(connection, CONNECTIONSTATE);
  262.  
  263.     /*If they're not the same, save the old one*/
  264.     if (!oldState || (GetInt(oldState) != state))
  265.     {
  266.     SetVar(connection, OLDCONNSTATE, oldState);
  267. #ifdef DEBUG
  268.     printf("Scian (%ld) connection %ld transition to %s\n",
  269.         getpid(), connection, stateName[state]);
  270. #endif
  271.     }
  272.  
  273.     /*Only some states have timeouts, disable them now*/
  274.     DoNotDisturb(connection, TIMEOUT);
  275.  
  276.     SetVar(connection, CONNECTIONSTATE, NewInt(state));
  277.  
  278.     /*Determine actions on the transition, such as doing a timeout*/
  279.     switch (state)
  280.     {
  281.     case CS_NAME_ONLY:
  282.         /*Set a timeout*/
  283.         SetTimeout(connection, TIMEOUT, WallClock() + SHORT_TIMEOUT);
  284.         break;
  285.     case CS_READ_NUMBER_ONE:
  286.         /*Must null the socket num first*/
  287.         SetVar(connection, READNUMBERONE, NULLOBJ);
  288.         break;
  289.     case CS_READ_NUMBER_TWO:
  290.         /*Must null the socket num first*/
  291.         SetVar(connection, READNUMBERTWO, NULLOBJ);
  292.         break;
  293.     case CS_READ_NUMBER_THREE:
  294.         /*Must null the socket num first*/
  295.         SetVar(connection, READNUMBERTHREE, NULLOBJ);
  296.         break;
  297.     case CS_READ_NUMBER_FOUR:
  298.         /*Must null the socket num first*/
  299.         SetVar(connection, READNUMBERFOUR, NULLOBJ);
  300.         break;
  301.     case CS_READ_PROC_NAME:
  302.         /*Must null the proc name first*/
  303.         SetVar(connection, CMDPROCNAME, NULLOBJ);
  304.         break;
  305.     case CS_IDLING:
  306.         /*Null the command name*/
  307.         SetVar(connection, CURCMD, NULLOBJ);
  308.         break;
  309.     case CS_WAIT_FOR_VERSION:
  310.         /*Null the command name*/
  311.         SetVar(connection, CURCMD, NULLOBJ);
  312.         SetTimeout(connection, TIMEOUT, WallClock() + SHORT_TIMEOUT);
  313.         break;
  314.     case CS_WAIT_FOR_PASSWORD:
  315.         /*Null the command name*/
  316.         SetTimeout(connection, TIMEOUT, WallClock() + SHORT_TIMEOUT);
  317.         SetVar(connection, CURCMD, NULLOBJ);
  318.         break;
  319.     default:
  320.         break;
  321.     }
  322. }
  323.  
  324. #ifdef PROTO
  325. static int GetConnectionState(ObjPtr connection)
  326. #else
  327. static int GetConnectionState(connection)
  328. ObjPtr connection;
  329. #endif
  330. /*Returns the state of the connection*/
  331. {
  332.     int state;
  333.     ObjPtr var;
  334.     var = GetIntVar("GetConnectionState", connection, CONNECTIONSTATE);
  335.     if (var)
  336.     {
  337.     state = GetInt(var);
  338.     }
  339.     else
  340.     {
  341.     state = CS_LIMBO;
  342.     }
  343.     return state;
  344. }
  345.  
  346. static ObjPtr TimeoutConnection(connection, elapsedTime)
  347. ObjPtr connection;
  348. double elapsedTime;
  349. /*Connection timeout, performing an action based on the state*/
  350. {
  351. #ifdef INTERACTIVE
  352.     WinInfoPtr alertWindow;
  353.     int state;
  354.     ObjPtr var;
  355.     char alertMessage[400];
  356.  
  357.     var = GetIntVar("TimeoutConnection", connection, CONNECTIONSTATE);
  358.     state = GetInt(var);
  359.  
  360.     switch (state)
  361.     {
  362.     case CS_NAME_ONLY:
  363.         var = GetIntVar("TimeoutConnection", connection, CONNECTIONKIND);
  364.         sprintf(alertMessage, "The SciAn %s did not respond during the time out period.  You can cancel \
  365. the connection or keep waiting.", GetInt(var) == CK_REMOTE_SCIAN ? "process" : "daemon");
  366.         alertWindow = AlertUser(UISEVEREALERT, (WinInfoPtr) connection, 
  367.         alertMessage, ContinueWaiting, 
  368.         2, "Cancel", "Keep Waiting");
  369.             if (alertWindow) SetVar((ObjPtr) alertWindow, HELPSTRING,
  370.     NewString("Something responded to the socket connection on the remote host, \
  371. but it did not identify itself as a SciAn process within the timeout period.  It \
  372. is possible but unlikely that some other process is running in the daemon's place \
  373. It is more likely that the process is just busy or slow, or there is a temporary \
  374. slowdown in the network."));
  375.         SetConnectionState(connection, CS_LIMBO);
  376.         break;
  377.     case CS_WAIT_FOR_VERSION:
  378.         var = GetIntVar("TimeoutConnection", connection, CONNECTIONKIND);
  379.         sprintf(alertMessage, "The SciAn %s did not respond during the time out period.  You can cancel \
  380. the connection or keep waiting.", GetInt(var) == CK_REMOTE_SCIAN ? "process" : "daemon");
  381.         alertWindow = AlertUser(UISEVEREALERT, (WinInfoPtr) connection, 
  382.         alertMessage, ContinueWaiting, 
  383.         2, "Cancel", "Keep Waiting");
  384.             if (alertWindow) SetVar((ObjPtr) alertWindow, HELPSTRING,
  385.     NewString("Something responded to the socket connection on the remote host, \
  386. but it did not identify itself as a SciAn process within the timeout period.  It \
  387. is possible but unlikely that some other process is running in the daemon's place \
  388. It is more likely that the process is just busy or slow, or there is a temporary \
  389. slowdown in the network."));
  390.         SetConnectionState(connection, CS_LIMBO);
  391.         break;
  392.     case CS_WAIT_FOR_PASSWORD:
  393.         sprintf(alertMessage, "An incoming connection has not validated itself as a SciAn process during the time out period.  You can cancel \
  394. the connection or keep waiting.");
  395.         alertWindow = AlertUser(UISEVEREALERT, (WinInfoPtr) connection, 
  396.         alertMessage, ContinueWaiting, 
  397.         2, "Cancel", "Keep Waiting");
  398.             if (alertWindow) SetVar((ObjPtr) alertWindow, HELPSTRING,
  399.     NewString("Something attempted to connect to this process, but, \
  400. but it did not identify itself as a SciAn process within the timeout period.  It \
  401. is possible but unlikely that some other process is running in the daemon's place \
  402. It is more likely that the process is just busy or slow, or there is a temporary \
  403. slowdown in the network."));
  404.         SetConnectionState(connection, CS_LIMBO);
  405.         break;
  406.     default:
  407.         ReportError("TimeoutConnection", "Internal State Error");
  408.         break;
  409.     }
  410.  
  411.     return ObjTrue;
  412. #endif
  413. }
  414.  
  415. static void HostNameErrorAlert()
  416. /*Creates a host name error*/
  417. {
  418.     WinInfoPtr alertWindow;
  419.     alertWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, 
  420.     "A host by that name or address could not be found.", ConnectToComputerAgain, 
  421.     2, "Cancel", "Re-enter");
  422.     if (alertWindow) SetVar((ObjPtr) alertWindow, HELPSTRING,
  423.     NewString("A valid host could not be found for that name or address.  \
  424. This may be it is not in the name server or the name server is not available.  You can check the \
  425. address to make sure that it is valid and try again."));
  426. }
  427.  
  428. #ifdef PROTO
  429. static void NoDaemonAlert(ObjPtr connection)
  430. #else
  431. static void NoDaemonAlert(connection)
  432. ObjPtr connection;
  433. #endif
  434. /*Creates a "no daemon" error*/
  435. {
  436.     WinInfoPtr alertWindow;
  437.     ObjPtr var;
  438.     char *message = "";
  439.  
  440.     var = GetIntVar("NoDaemonAlert", connection, CONNECTIONKIND);
  441.     if (var)
  442.     {
  443.     switch(GetInt(var))
  444.     {
  445.         case CK_REMOTE_DAEMON:
  446.         message = "There is no SciAn network daemon running on that host.";
  447.         break;
  448.         case CK_LOCAL_DAEMON:
  449.         message = "There is no SciAn network daemon running on your local computer.";
  450.         break;
  451.         default:
  452.         message = "Internal State Error in NoDaemonAlert";
  453.         break;
  454.     }
  455.     }
  456.  
  457.     alertWindow = AlertUser(UISEVEREALERT, (WinInfoPtr) 0, 
  458.     message, ConnectToComputerAgain, 
  459.     2, "Cancel", "Re-enter");
  460.     if (alertWindow) SetVar((ObjPtr) alertWindow, HELPSTRING,
  461.     NewString("In order for you to be able to connect \
  462. to SciAn processes running on a computer, the SciAn network daemon must be running \
  463. on the computer.  The SciAn network daemon can by started by entering 'snd &' on \
  464. the command line of the host computer."));
  465. }
  466.  
  467. static ObjPtr KillConnection(connection)
  468. ObjPtr connection;
  469. /*Kills a connection*/
  470. {
  471.     DeleteFromList(allConnections, connection);
  472.     return ObjTrue;
  473. }
  474.  
  475. void FindCommand(connection)
  476. ObjPtr connection;
  477. /*Finds a command corresponding to CURCMD in connection and changes the
  478. connection's state appropriately to deal with it.*/
  479. {
  480.     ObjPtr command;
  481.     command = GetVar(connection, CURCMD);
  482.  
  483.     if (command)
  484.     {
  485.     char *cmd;
  486.     cmd = GetString(command);
  487.  
  488. #ifdef DEBUG
  489. fprintf(stderr, "received header of %s command\n", cmd);
  490. #endif
  491.  
  492.     if (strlen(cmd) == 4)
  493.     {
  494.         long cmdNum;
  495.  
  496.         cmdNum = CMD(cmd);
  497.  
  498.         if (cmdNum == CMD(ND_INFO_LIVE_PROCESS) ||
  499.         cmdNum == CMD(ND_INFO_DEAD_PROCESS))
  500.         {
  501.         /*Live or dead process*/
  502.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  503.         }
  504.         else if (cmdNum == CMD(ND_CLOSE))
  505.         {
  506.         SetConnectionState(connection, CS_MORIBUND);
  507.         }
  508.         /* This may be temporary. provides an exit for comp process */
  509.         else if (libRunning && cmdNum == CMD(ND_EXIT))
  510.         {
  511.         SetConnectionState(connection, CS_MORIBUND);
  512.         fprintf(stderr, "Got exit command, turning off library\n");
  513.         libRunning = 0;
  514.         }
  515.         else if (cmdNum == CMD(ND_LIST_OBJECTS))
  516.         {
  517.         ThingListPtr runner;
  518.  
  519.         runner = LISTOF(allAdvertised);
  520.         while (runner)
  521.         {
  522.             sprintf (tempStr, "%s %ld\n", ND_REG_OBJECT, GetInt(GetIntVar("FindCommand", runner -> thing, NETWORKID)));
  523.             SendSocketCommandLater(connection,tempStr);
  524.             SendObjectLater(connection, runner -> thing);
  525.             runner = runner -> next;
  526.         }
  527.         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  528.         }
  529.         else if (cmdNum == CMD(ND_REG_OBJECT))
  530.         {
  531.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  532.         }
  533.         else if (cmdNum == CMD(NO_MESG_OBJECT))
  534.         {
  535.         SetConnectionState(connection, CS_READ_OBJECT);
  536.         }
  537.         else if (cmdNum == CMD(NO_MESG_SEND_OBJECT))
  538.         {
  539.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  540.         }
  541.         else if (cmdNum == CMD(NO_MESG_GETVAR))
  542.         {
  543.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  544.         }
  545.         else if (cmdNum == CMD(NO_MESG_GETELEMENT))
  546.         {
  547.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  548.         }
  549.         else if (cmdNum == CMD(NO_MESG_GOTVAR))
  550.         {
  551.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  552.         }
  553.         else if (cmdNum == CMD(NO_MESG_GOTELEMENT))
  554.         {
  555.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  556.         }
  557. #ifndef NEWSTYLEUPDATES
  558.         else if (cmdNum == CMD(NO_MESG_UPDATEVAR))
  559.         {
  560.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  561.         }
  562. #else
  563.         else if (cmdNum == CMD(NO_MESG_UPDATEVAR_ID))
  564.         {
  565.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  566.         }
  567.         else if (cmdNum == CMD(NO_MESG_UPDATEVAR_SEND))
  568.         {
  569.         SetConnectionState(connection, CS_READ_NUMBER_ONE);
  570.         }
  571. #endif
  572.         else if (cmdNum == CMD(NO_MESG_MACHINE_IRIS4D))
  573.         {
  574. #if MACHINE == IRIS4D
  575. fprintf(stderr, "fast socket\n");
  576.         SetVar(connection, FASTSOCKET, ObjTrue);
  577. #endif
  578.         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  579.         }
  580.         else if (cmdNum == CMD(NO_MESG_MACHINE_RS6000))
  581.         {
  582. #if MACHINE == RS6000
  583. #endif
  584.         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  585.         }
  586.         else if (cmdNum == CMD(NO_MESG_MACHINE_UNKNOWN))
  587.         {
  588.         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  589.         }
  590.         else
  591.         {
  592.         sprintf(tempStr, "Bad socket command: %s", cmd);
  593.         ReportError("FindCommand", tempStr);
  594.         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  595.         }
  596.     }
  597.     else
  598.     {
  599.         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  600.         ReportError("FindCommand", "Socket command wrong size");
  601.     }
  602.     }
  603.     else
  604.     {
  605.     SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  606.     ReportError("FindCommand", "No command specified");
  607.     }
  608. }
  609.  
  610. #ifdef PROTO
  611. Bool ThisWouldBeAReallyBadThing(NameTyp var)
  612. #else
  613. Bool ThisWouldBeAReallyBadThing(var)
  614. NameTyp var;
  615. #endif
  616. {
  617.     switch(var)
  618.     {
  619.     case SELECTED:
  620.         return true;
  621.     case NETWORKID:
  622.         return true;
  623.     case OWNERCONNECTION:
  624.         return true;
  625. /*    case CPALETTE:
  626.         return true; */    /* HAK temporary kludge */
  627.     case PREFVIS:
  628.         return true;    /* can't handle vis classes (only datasets) */
  629.     default:
  630.         return false;
  631.     }
  632. }
  633.  
  634. #ifdef PROTO
  635. void SendGetVarMessage(ObjPtr obj, NameTyp var)
  636. #else
  637. void SendGetVarMessage(obj, var)
  638. ObjPtr obj;
  639. NameTyp var;
  640. #endif
  641. {
  642.     ObjPtr connection;
  643.     int netid;
  644.  
  645.     /* object had better be a Remote object */
  646.     connection = GetVar(obj, OWNERCONNECTION);
  647.     if (!connection)
  648.     {
  649.     ReportError("SendGetVarMessage", "object has no OWNERCONNECTION");
  650.     }
  651.     netid = GetInt(GetVar(obj, NETWORKID));
  652.     if (!netid)
  653.     {
  654.     ReportError("SendGetVarMessage", "object has no NETWORKID");
  655.     }
  656.     if (connection && netid)
  657.     {
  658.     sprintf(tempStr, "%s %d %d\n", NO_MESG_GETVAR, netid, var);
  659.     SendSocketCommandLater(connection, tempStr);
  660.     }
  661. }
  662.  
  663. void SendSendObjectMessage(ObjPtr connection, unsigned long netid)
  664. {
  665.     ObjPtr process;
  666.  
  667.     if (!netid)
  668.     {
  669.     ReportError("SendSendObjectMessage", "netid = 0!");
  670.     }
  671.     else if (!connection)
  672.     {
  673.     ReportError("SendSendObjectMessage", "connection nil");
  674.     }
  675.     else if (!(process = GetVar(connection, OWNERPROCESS)))
  676.     {
  677.     ReportError("SendSendObjectMessage", "connection has no OWNERPROCESS");
  678.     }
  679.     else
  680.     {
  681.     sprintf(tempStr, "%s %ld\n", NO_MESG_SEND_OBJECT, netid);
  682.     SendSocketCommandLater(connection, tempStr);
  683.     NetworkIDIsWaiting(process, netid, true);
  684.     }
  685. }
  686.  
  687. #ifdef PROTO
  688. void SendGetElementMessage(ObjPtr obj, NameTyp el)
  689. #else
  690. void SendGetElementMessage(obj, var)
  691. ObjPtr obj;
  692. NameTyp var;
  693. #endif
  694. {
  695.     ObjPtr connection;
  696.     int netid;
  697.  
  698.     /* object had better be a Remote object */
  699.     connection = GetVar(obj, OWNERCONNECTION);
  700.     netid = GetInt(GetVar(obj, NETWORKID));
  701.     if (connection && netid)
  702.     {
  703.     sprintf(tempStr, "%s %d %d\n", NO_MESG_GETELEMENT, netid, el);
  704.     SendSocketCommandLater(connection, tempStr);
  705.     }
  706.     else
  707.     {
  708.     ReportError("SendGetElementMessage", "object has no OWNERCONNECTION or NETWORKID");
  709.     }
  710. }
  711.  
  712. #ifdef PROTO
  713. void SendVarUpdateNotice(ObjPtr obj, NameTyp var)
  714. #else
  715. void SendVarUpdateNotice(obj, var)
  716. ObjPtr obj;
  717. NameTyp var;
  718. #endif
  719. {
  720.     ThingListPtr runner;
  721.     int netid;
  722.     VarsPtr vptr;
  723.  
  724.     netid = GetInt(GetVar(obj, NETWORKID));
  725.     if (!netid)
  726.     {
  727.     ReportError("SendVarUpdateNotice", "object has no NETWORKID");
  728.     return;
  729.     }
  730.     runner = LISTOF(allConnections);
  731.     while (runner)
  732.     {
  733.     /* any non-daemon connection */
  734.     if (CK_LOCAL_SCIAN == GetInt(GetIntVar("SendVarUpdateNotice", runner -> thing, CONNECTIONKIND)))
  735.     {
  736. #ifndef NEWSTYLEUPDATES
  737.         sprintf(tempStr, "%s %ld %ld\n", NO_MESG_UPDATEVAR, netid, var);
  738.         SendSocketCommandLater(runner -> thing, tempStr);
  739. #else
  740.         vptr = GetVarNode(obj, var);
  741.         if (!vptr)
  742.         {
  743. fprintf(stderr, "something funny happened\n");
  744.         sprintf(tempStr, "%s %ld %ld %ld %ld \n", NO_MESG_UPDATEVAR, netid, var, 0, 0);
  745.         SendSocketCommandLater(runner -> thing, tempStr);
  746.         }
  747. /* HAK */
  748. #if 0
  749.         else if ( 0 && ObjectWasSent(vptr -> value, runner -> thing))
  750. #else
  751.         else if (ObjectWasSent(vptr -> value, runner -> thing))
  752. #endif
  753.         {
  754.         unsigned long valNetID;
  755.  
  756.         valNetID = PublishObject(vptr -> value);
  757.         sprintf(tempStr, "%s %ld %ld %ld %ld \n", NO_MESG_UPDATEVAR_ID, netid, var, valNetID, vptr -> chCount);
  758.         SendSocketCommandLater(runner -> thing, tempStr);
  759.         }
  760.         else
  761.         {
  762.         unsigned long valNetID;
  763.  
  764.         valNetID = PublishObject(vptr -> value);
  765.         sprintf(tempStr, "%s %ld %ld %ld %ld \n", NO_MESG_UPDATEVAR_SEND, netid, var, valNetID, vptr -> chCount);
  766.         SendSocketCommandLater(runner -> thing, tempStr);
  767.         if (vptr -> value)
  768.             SendObjectLater(runner -> thing, vptr -> value);
  769.         }
  770. #endif
  771.     }
  772.     runner = runner -> next;
  773.     }
  774. }
  775.  
  776. ObjPtr AdvertiseObject(object)
  777. ObjPtr object;
  778. /*Advertises an object*/
  779. {
  780.     ObjPtr networkID;
  781.     int netid;
  782.     ThingListPtr runner; /* runs down connection list */
  783.  
  784.     if (GetPredicate(object, ADVERTISED))
  785.     {
  786.     /* already advertised */
  787.     return ObjFalse;
  788.     }
  789.  
  790.     SetVar (object, ADVERTISED, ObjTrue);
  791.  
  792.     netid = PublishObject(object);
  793.  
  794.     PrefixList (allAdvertised, object);
  795.  
  796.     runner = LISTOF(allConnections);
  797.     while (runner)
  798.     {
  799.     /* any non-daemon connection */
  800.     if (CK_LOCAL_SCIAN == GetInt(GetIntVar("AdvertiseObject", runner -> thing, CONNECTIONKIND)))
  801.     {
  802.         sprintf(tempStr, "%s %ld\n", ND_REG_OBJECT, netid);
  803.         SendSocketCommandLater(runner -> thing, tempStr);
  804.         SendObjectLater(runner -> thing, object);
  805.     }
  806.     runner = runner -> next;
  807.     }
  808.     
  809.     return ObjTrue;
  810. }
  811.  
  812. ObjPtr UnadvertiseObject(object)
  813. ObjPtr object;
  814. /*Unadvertises an object*/
  815. {
  816.     ThingListPtr runner;
  817.     if (!GetPredicate(object, ADVERTISED))
  818.     {
  819.     /* never advertised, or already unadvertised */
  820.     return ObjFalse;
  821.     }
  822.  
  823.     SetVar (object, ADVERTISED, ObjFalse);
  824.  
  825.     DeleteFromList(allAdvertised, object);
  826.  
  827.     runner = LISTOF(allConnections);
  828.     while (runner)
  829.     {
  830.     if (CK_LOCAL_SCIAN == GetInt(GetIntVar("AdvertiseObject", runner -> thing, CONNECTIONKIND)))
  831.     {
  832.         sprintf(tempStr, "%s %ld %ld\n", ND_UNREG_OBJECT, GetIntVar("AdvertiseObject", runner -> thing, NETWORKID));
  833.         SendSocketCommandLater(runner -> thing, tempStr);
  834.     }
  835.     runner = runner -> next;
  836.     }
  837.  
  838.     return ObjTrue;
  839. }
  840.  
  841. #ifdef PROTO
  842. static ObjPtr NewProcess(ObjPtr connection, char *procName, int procSocket)
  843. #else
  844. static ObjPtr NewProcess(connection, procName, procSocket)
  845. ObjPtr connection;
  846. char *procName;
  847. int procSocket;
  848. #endif
  849. /*Registers a process with the given name and num from connection*/
  850. {
  851.     WinInfoPtr dialogExists;
  852.     ObjPtr allProcesses;
  853.     ObjPtr process;
  854.  
  855.     /*Make a new process*/
  856.     process = NewObject(processClass, 0);
  857.     SetVar(process, NAME, NewString(procName));
  858.     SetVar(process, SOCKETID, NewInt(procSocket));
  859.     SetVar(process, OWNERCONNECTION, connection);
  860.     SetVar(process, ALLOBJECTS, NewList());
  861.     SetVar(process, ALLADVERTISED, NewList());
  862.  
  863.     /*Add to the list of all processes*/
  864.     allProcesses = GetListVar("NewProcess", connection, ALLPROCESSES);
  865.     if (allProcesses)
  866.     {
  867.     PrefixList(allProcesses, process);
  868.     }
  869.  
  870.     dialogExists = DialogExists((WinInfoPtr) connection, NewString("Controls"));
  871.     if (dialogExists)
  872.     {
  873.     ObjPtr icon, corral;
  874.  
  875.     /*Make an icon and put it in the corral*/
  876.     corral = GetObjectVar("NewProcess", (ObjPtr) dialogExists, CORRAL);
  877.     if (!corral) return NULLOBJ;
  878.  
  879.     icon = NewObject(processIcon, 0L);
  880.     SetVar(icon, ICONLOC, NULLOBJ);
  881.  
  882.     SetVar(icon, NAME, NewString(procName));
  883.     SetVar(icon, REPOBJ, process);
  884.     SetVar(icon, CORRAL, corral);
  885.     DropIconInCorral(corral, icon);
  886.     }
  887.  
  888.     return process;
  889. }
  890.  
  891. #ifdef PROTO
  892. Bool IsNetworkIDWaiting(ObjPtr process, unsigned long netid)
  893. #else
  894. Bool IsNetworkIDWaiting(process, netid)
  895. ObjPtr process;
  896. unsigned long netid;
  897. #endif
  898. {
  899.     ObjPtr netWaiting;
  900.     ThingListPtr runner;
  901.  
  902.     if (netid == NETSTUBFLAG)
  903.     {
  904.     return true;
  905.     }
  906.  
  907. #ifdef DEBUG
  908. fprintf(stderr, "IsNetworkIDWaiting: process %lx, looking for netid %d\n", process, netid);
  909. #endif
  910.  
  911.     netWaiting = GetVar(process, NETWAITINGOBJECTS);
  912.     if (!netWaiting || !IsList(netWaiting))
  913.     {
  914.     netWaiting = NewList();
  915.     SetVar (process, NETWAITINGOBJECTS, netWaiting);
  916.     }
  917.  
  918.     runner = LISTOF(netWaiting);
  919.     while (runner)
  920.     {
  921.     if (netid == GetInt(runner -> thing))
  922.     {
  923.         return true;
  924.     }
  925.     runner = runner -> next;
  926.     }
  927.     return false;
  928. }
  929.  
  930. #ifdef PROTO
  931. void NetworkIDIsWaiting(ObjPtr process, unsigned long netid, Bool flag)
  932. #else
  933. void NetworkIDIsWaiting(process, netid, flag)
  934. ObjPtr process;
  935. unsigned long netid;
  936. Bool flag;
  937. #endif
  938. {
  939.     ObjPtr netWaiting;
  940.  
  941. #ifdef DEBUG
  942. fprintf(stderr, "making id # %ld waiting %s\n", netid, flag ? "true" : "false");
  943. #endif
  944.  
  945.     netWaiting = GetVar(process, NETWAITINGOBJECTS);
  946.     if (!netWaiting || !IsList(netWaiting))
  947.     {
  948.     netWaiting = NewList();
  949.     if (flag)
  950.         PrefixList(netWaiting, NewInt(netid));
  951.     SetVar (process, NETWAITINGOBJECTS, netWaiting);
  952.     }
  953.     else if (flag)
  954.     {
  955.     if (!IsNetworkIDWaiting(process, netid))
  956.     {
  957.         PrefixList(netWaiting, NewInt(netid));
  958.         SetVar (process, NETWAITINGOBJECTS, netWaiting);
  959.     }
  960.     }
  961.     else
  962.     {
  963.     if (IsNetworkIDWaiting(process, netid))
  964.     {
  965.         ThingListPtr *runner;
  966.         runner = &LISTOF(netWaiting);
  967.         /* delete all occurences of netid from list */
  968.         while (*runner)
  969.         {
  970.         if (netid == GetInt((*runner) -> thing))
  971.         {
  972.             ThingListPtr next;
  973.             next = (*runner) -> next;
  974.             Free(*runner);
  975.             *runner = next;
  976.         }
  977.         else
  978.         {
  979.             runner = &((*runner) -> next);
  980.         }
  981.         }
  982.     }
  983.     }
  984. }
  985.  
  986. Bool ObjectWasSent(obj, connection)
  987. ObjPtr obj, connection;
  988. {
  989.     ThingListPtr runner;
  990.     ObjPtr netidObj;
  991.     unsigned long netid;
  992.     ObjPtr allSentList;
  993.  
  994.     if (!(netidObj = GetVar(obj, NETWORKID)))
  995.     {
  996.     return false;
  997.     }
  998.     netid = GetInt(netidObj);
  999.  
  1000.     allSentList = GetVar(connection, ALLSENTLIST);
  1001.     if (!allSentList)
  1002.     {
  1003.     return false;
  1004.     }
  1005. /* fprintf(stderr, "looking for %ld... ", netid); */
  1006.     runner = LISTOF(allSentList);
  1007.     while (runner)
  1008.     {
  1009. /* fprintf(stderr, "%ld ", GetInt(GetVar(runner -> thing, NETWORKID))); */
  1010.     if (netid == GetInt(GetVar(runner -> thing, NETWORKID)))
  1011.     {
  1012. /* fprintf(stderr, "Found it!\n"); */
  1013.         return true;
  1014.     }
  1015.     runner = runner -> next;
  1016.     }
  1017. /* fprintf(stderr, "didn't find it..\n"); */
  1018.     return false;
  1019. }
  1020.  
  1021. #ifdef PROTO
  1022. ObjPtr FindRemoteObject(ObjPtr process, int netid, Bool getFlag)
  1023. #else
  1024. ObjPtr FindRemoteObject(process, netid, getFlag)
  1025. ObjPtr process;
  1026. int netid;
  1027. Bool getFlag
  1028. #endif
  1029. {
  1030.     ObjPtr allObjects;
  1031.     ThingListPtr runner;
  1032.  
  1033.  
  1034.     if (netid == NETSTUBFLAG)
  1035.     {
  1036.     return NULLOBJ;
  1037.     }
  1038.  
  1039.     allObjects = GetVar(process, ALLOBJECTS);
  1040.     if (!allObjects || !IsList(allObjects))
  1041.     {
  1042.     allObjects = NewList();
  1043.     SetVar (process, ALLOBJECTS, allObjects);
  1044.     }
  1045.  
  1046.     runner = LISTOF(allObjects);
  1047.     while(runner)
  1048.     {
  1049.     if (netid == GetInt(GetVar(runner -> thing, NETWORKID)))
  1050.     {
  1051.         break;
  1052.     }
  1053.     runner = runner -> next;
  1054.     }
  1055.  
  1056.     if (runner)
  1057.     {
  1058.     return runner -> thing;
  1059.     }
  1060.     else
  1061.     {
  1062.     if (getFlag)
  1063.     {
  1064.         ThingListPtr runner;
  1065.         ObjPtr connection = NULLOBJ;
  1066.  
  1067.         runner = LISTOF(allConnections);
  1068.         while (runner)
  1069.         {
  1070.         if (GetVar(runner -> thing, OWNERPROCESS) == process)
  1071.         {
  1072.             connection = runner -> thing;
  1073.             break;
  1074.         }
  1075.         runner = runner -> next;
  1076.         }
  1077.         if (connection)
  1078.         {
  1079.         ObjPtr retVal;
  1080.  
  1081.         if (!IsNetworkIDWaiting(process, netid))
  1082.         {
  1083.             SendSendObjectMessage(connection, netid);
  1084.         }
  1085.  
  1086.         WaitForNetObject(connection, netid);
  1087.         if (retVal = FindRemoteObject(process, netid, false))
  1088.         {
  1089.             return retVal;
  1090.         }
  1091.         else
  1092.         {
  1093.             ReportError("FindRemoteObject", "Internal error (probably timeout)");
  1094.         }
  1095.         }
  1096. #ifdef PARANOID
  1097.         else
  1098.         {
  1099.         ReportError("FindRemoteObject", "No connection found for process");
  1100.         }
  1101. #endif
  1102.     }
  1103.     }
  1104.     return NULLOBJ; /* only if not found ( && flag == false) or was an error */
  1105. }
  1106.  
  1107. #ifdef PROTO
  1108. static void DeleteProcess(ObjPtr connection, int socketNum)
  1109. #else
  1110. static void DeleteProcess(connection, socketNum)
  1111. ObjPtr connection;
  1112. int socketNum;
  1113. #endif
  1114. /*Deletes a process with the given name and num from connection*/
  1115. {
  1116.     WinInfoPtr dialogExists;
  1117.     ObjPtr allProcesses;
  1118.     ObjPtr process = NULLOBJ;
  1119.     ThingListPtr runner;
  1120.     /*Find the process*/
  1121.     allProcesses = GetListVar("DeleteProcess", connection, ALLPROCESSES);
  1122.     if (allProcesses)
  1123.     {
  1124.     runner = LISTOF(allProcesses);
  1125.     while (runner)
  1126.     {
  1127.         ObjPtr var;
  1128.         var = GetVar(runner -> thing, SOCKETID);
  1129.         if (var && socketNum == GetInt(var))
  1130.         {
  1131.         process = runner -> thing;
  1132.         }
  1133.         runner = runner -> next;
  1134.     }
  1135.     }
  1136.  
  1137.     if (process)
  1138.     {
  1139.     DeleteFromList(allProcesses, process);
  1140.  
  1141.         dialogExists = DialogExists((WinInfoPtr) connection, NewString("Controls"));
  1142.     if (dialogExists)
  1143.     {
  1144.         ObjPtr contents, corral, delIcon = NULLOBJ;
  1145.  
  1146.         /*Delete the icon from the corral*/
  1147.         corral = GetObjectVar("DeleteProcess", (ObjPtr) dialogExists, CORRAL);
  1148.         if (!corral) return;
  1149.  
  1150.         contents = GetListVar("DeleteProcess", corral, CONTENTS);
  1151.         if (!contents) return;
  1152.         runner = LISTOF(contents);
  1153.         while (runner)
  1154.         {
  1155.         if (GetVar(runner -> thing, REPOBJ) == process)
  1156.         {
  1157.             delIcon = runner -> thing;
  1158.         }
  1159.         runner = runner -> next;
  1160.         }
  1161.         DeleteFromList(contents, delIcon);
  1162.         ImInvalid(corral);
  1163.     }
  1164.     }
  1165. }
  1166.  
  1167. #if 0
  1168. #ifdef PROTO
  1169. void FlagObjectAsChanging(ObjPtr obj)
  1170. #else
  1171. void FlagObjectAsChanging(obj)
  1172. ObjPtr obj;
  1173. #endif
  1174. {
  1175.     HAK!
  1176. }
  1177. #endif
  1178.  
  1179. static ObjPtr NewRemoteObject(filledObj)
  1180. ObjPtr filledObj;
  1181. /*Method to register a new remote object and add its icon to the process window*/
  1182. {
  1183.     WinInfoPtr dialogExists;
  1184.     ObjPtr connection, process;
  1185.  
  1186.     connection = GetVar(filledObj, OWNERCONNECTION);
  1187.     if (!connection)
  1188.     {
  1189.     ReportError("NewRemoteObject", "Object has no connection");
  1190.     return ObjFalse;
  1191.     }
  1192.  
  1193.     process = GetVar(connection, OWNERPROCESS);
  1194.     if (!process)
  1195.     {
  1196.     ReportError("NewRemoteObject", "John lied");
  1197.     return ObjFalse;
  1198.     }
  1199.  
  1200.     dialogExists = DialogExists((WinInfoPtr) process, NewString("Controls"));
  1201.     if (dialogExists)
  1202.     {
  1203.     ObjPtr icon, corral, name;
  1204.  
  1205.     /*Make an icon and put it in the corral*/
  1206.     corral = GetObjectVar("NewRemoteObject", (ObjPtr) dialogExists, CORRAL);
  1207.     MakeVar(filledObj, DEFAULTICON);
  1208.     icon = GetVar(filledObj, DEFAULTICON);
  1209.     if (icon)
  1210.     {
  1211.         icon = NewObject(icon, 0L);
  1212.     }
  1213.     else
  1214.     {
  1215.         icon = NewIcon(ICONQUESTION, 0, 0, "?");
  1216.     }
  1217.         SetVar(icon, ICONLOC, NULLOBJ);
  1218.     MakeVar(filledObj, NAME);
  1219.     name = GetVar(filledObj, NAME);
  1220.         SetVar(icon, NAME, name);
  1221.     SetVar(icon, FORMAT, GetVar(process, NAME)); 
  1222.         SetVar(icon, REPOBJ, filledObj);
  1223.         SetVar(icon, CORRAL, corral);
  1224.         DropIconInCorral(corral, icon);
  1225.     }
  1226.     return ObjTrue;
  1227. }
  1228.  
  1229. #ifdef PARANOID
  1230. int ICCount = 0;
  1231. #endif
  1232.  
  1233. #ifdef PROTO
  1234. Bool IdleConnection(ObjPtr connection)
  1235. #else
  1236. void IdleConnection(connection)
  1237. ObjPtr connection;
  1238. #endif
  1239. /*Idles a connection*/
  1240. {
  1241.     int state;
  1242.     Bool retVal;
  1243.  
  1244.     retVal = false;
  1245.  
  1246. #ifdef PARANOID
  1247.     if (++ICCount > 1)
  1248.     ReportError("IdleConnection", "HEY! Multiple calls are active! Very bad!\n");
  1249. #endif
  1250.  
  1251.     state = GetConnectionState(connection);
  1252.  
  1253.     switch (state)
  1254.     {
  1255.     case CS_NOT_LISTENING:        /*Accepting socket, not listening*/
  1256.         {
  1257.         struct sockaddr_in templateAddr;
  1258.         int template;
  1259.         int proto;
  1260.         int port;
  1261.  
  1262.         /*Initialize internet socket template to internet, any machine*/
  1263.         port = SocketPort();
  1264.         templateAddr . sin_port = port;
  1265.         templateAddr . sin_family = PF_INET;
  1266.         templateAddr . sin_addr.s_addr = INADDR_ANY;
  1267.  
  1268.         proto = getprotobyname("tcp") -> p_proto;
  1269.         template = socket(PF_INET, SOCK_STREAM, proto);
  1270.         if (template >= 0)
  1271.         {
  1272.             int status;
  1273.  
  1274.             status = bind(template, &templateAddr, sizeof(templateAddr));
  1275.             if (status >= 0)
  1276.             {
  1277.             ObjPtr localConnection;
  1278.             /*Name was bound OK*/
  1279.  
  1280.             /*Set socket to be non blocking*/
  1281. #if MACHINE == IRIS4D
  1282.             fcntl(template, F_SETFL, 
  1283.                 fcntl(template, F_GETFL) | FNDELAY);
  1284. #else
  1285.             fcntl(template, F_SETFL, 
  1286.                 fcntl(template, F_GETFL) | O_NDELAY);
  1287.             fcntl(template, F_SETFL,
  1288.                 fcntl(template, F_GETFL) | O_NONBLOCK);
  1289. #endif
  1290.  
  1291.             /*Listen for a maximum of 5 connections*/
  1292.             listen(template, 5);
  1293.             ((ConnectionPtr) connection) -> template = template;
  1294.             SetVar(connection, SOCKETID, NewInt(port));
  1295.  
  1296.             /*Send out a newp, now that we know who we are*/
  1297.             localConnection = NewLocalDaemonConnection();
  1298.             sprintf(tempStr, "%s %d %d %s_(%d)\n", 
  1299.                 ND_REG_PROCESS, getpid(), port, whatsMyName, getpid());
  1300.             SendSocketCommandLater(localConnection, tempStr);
  1301.  
  1302.             SetConnectionState(connection, CS_LISTENING);
  1303.             }
  1304.             else
  1305.             {
  1306.             /*Connection failed, try again later.*/
  1307.             }
  1308.         }
  1309.         else
  1310.         {
  1311.             ReportError("IdleSockets", "socket call failed!");
  1312.         }
  1313.         }
  1314.         break;
  1315.     case CS_LISTENING:        /*Accepting socket, listening*/
  1316.         {
  1317.         int sock, template;
  1318.  
  1319.         template = ((ConnectionPtr) connection) -> template;
  1320.         if (template >= 0)
  1321.         {
  1322.             sock = accept(template, (struct sockaddr *) 0, (int *) 0);
  1323.             if (sock != -1)
  1324.             {
  1325.             ObjPtr newConnection;
  1326.  
  1327.             /*Wow, a connection*/ printf("Wow, a connection\n");
  1328.             newConnection = NewLocalScianConnection(sock);
  1329.             }
  1330.             else
  1331.             {
  1332.             /*No connection yet*/
  1333.             break;
  1334.             }
  1335.         }
  1336.         else
  1337.         {
  1338.             ReportError("IdleSocket", "Bad listener template");
  1339.         }
  1340.         }
  1341.         break;
  1342.     case CS_NAME_ONLY:        /*We've got the name only*/
  1343.         {
  1344.         struct hostent *host;
  1345.         ObjPtr name;
  1346.         char *s;
  1347.         struct sockaddr_in inSocketAddr;
  1348.         WinInfoPtr alertWindow;
  1349.  
  1350.         name = GetStringVar("IdleConnection", connection, NAME);
  1351.         if (!name)
  1352.         {
  1353.             break;
  1354.         }
  1355.  
  1356.         /*Try to get the host information based on the address or name*/
  1357.         host = gethostbyname(GetString(name));
  1358.  
  1359.         if (host)
  1360.         {
  1361.             ObjPtr var;
  1362.             int k, inSocket, port;
  1363.             struct protoent *proto;
  1364.  
  1365.             /*Now try to connect*/
  1366.             for (k = 0; k < sizeof(inSocketAddr); ++k)
  1367.             {
  1368.             *(k + (char *) &inSocketAddr) = 0;
  1369.             }
  1370.             for (k = 0; k < host -> h_length; ++k)
  1371.             {
  1372.             *(k + (char *) &inSocketAddr . sin_addr) =
  1373.                 *(k + (char *) host -> h_addr);
  1374.                 }
  1375.             var = GetVar(connection, SOCKETID);
  1376.             if (var)
  1377.             {
  1378.             port = GetInt(var);
  1379.             }
  1380.             else
  1381.             {
  1382.             port = ND_BASE_SOCKET_NUMBER;
  1383.             }
  1384.             inSocketAddr . sin_port = htons((u_short) port);
  1385.             inSocketAddr . sin_family = PF_INET;    /*Internet protocol*/
  1386.  
  1387.             proto = getprotobyname("tcp");
  1388.  
  1389.             inSocket = socket(PF_INET, SOCK_STREAM, proto -> p_proto);
  1390.             if (inSocket >= 0)
  1391.             {
  1392.             int status;
  1393.  
  1394.              status = connect(inSocket, &inSocketAddr, sizeof(inSocketAddr));
  1395.             if (status >= 0)
  1396.             {
  1397.                 /*Set socket to be non blocking*/
  1398.                 fcntl(inSocket, F_SETFL, 
  1399.                 fcntl(inSocket, F_GETFL) | FNDELAY);
  1400.  
  1401.                 /*Send a validator*/
  1402.                 sprintf(tempStr, "%s\n", ND_PASSWORD);
  1403.                 writen(inSocket, tempStr, strlen(tempStr));
  1404.  
  1405.                 /*Put the fd into the connection*/
  1406.                 ((ConnectionPtr) connection) -> sock = inSocket;
  1407.  
  1408.                 /*Set the state*/
  1409.                 SetConnectionState(connection, CS_WAIT_FOR_VERSION);
  1410.             }
  1411.             else
  1412.             {
  1413.                 NoDaemonAlert(connection);
  1414.                 SetConnectionState(connection, CS_MORIBUND);
  1415.             }
  1416.             }
  1417.             else
  1418.             {
  1419.             ReportError("IdleSocket", "Problem making socket.");
  1420.             SetConnectionState(connection, CS_MORIBUND);
  1421.             }
  1422.         }
  1423.         else
  1424.         {
  1425.             /*Error with the host name.*/
  1426.             switch (h_errno)
  1427.             {
  1428.             case HOST_NOT_FOUND:        /*No host by that name*/
  1429.             default:            /*Any other fatal error*/
  1430.                 HostNameErrorAlert();
  1431.                 SetConnectionState(connection, CS_MORIBUND);
  1432.                 break;
  1433.             case TRY_AGAIN:            /*Temporary error*/
  1434.                 break;
  1435.             }
  1436.         }
  1437.         }
  1438.         break;
  1439.     case CS_WAIT_FOR_VERSION:            /*Waiting for a VERS to come back*/
  1440.         {
  1441.         int sock;
  1442.         int nChars;
  1443.         ObjPtr command;
  1444.         ObjPtr curCmd;
  1445.  
  1446.         curCmd = GetVar(connection, CURCMD);
  1447.         if (!curCmd) curCmd = NewString(""); 
  1448.  
  1449.         sock = ((ConnectionPtr) connection) -> sock;
  1450.         if (sock >= 0)
  1451.         {
  1452.             Bool anything;
  1453.             char inChar;
  1454.             anything = false;
  1455.  
  1456.             /*See if there are characters waiting*/
  1457.             while ((1 == read(sock, &inChar, 1)) &&
  1458.                inChar &&
  1459.                !isspace(inChar))
  1460.             {
  1461.             char cmd[2];
  1462.             /*There's a command of some sort*/
  1463.             cmd[0] = inChar;
  1464.             cmd[1] = 0;
  1465.  
  1466.             curCmd = ConcatStrings(curCmd, NewString(cmd));
  1467.             anything = true;
  1468.             }
  1469.             if (anything)
  1470.             {
  1471.             SetVar(connection, CURCMD, curCmd);
  1472.             if (inChar == '\n' || inChar == 0)
  1473.             {
  1474.                 ((ConnectionPtr) connection) -> gotCmdEnd = true;
  1475.             }
  1476.             if (inChar == 0 || isspace(inChar))
  1477.             {
  1478.                 char *cmd;
  1479.  
  1480.                 /*The command is done.  Find it*/
  1481.                 cmd = GetString(curCmd);
  1482.                 if (strlen(cmd) == 4 && CMD(cmd) == CMD(ND_INFO_VERSION))
  1483.                 {
  1484.                 ObjPtr var;
  1485.                 /*Got a version.  Either register our process
  1486.                   or ask for updates*/
  1487.  
  1488.                 var = GetIntVar("IdleSocket", connection, CONNECTIONKIND);
  1489.                 if (var)
  1490.                 {
  1491.                     switch (GetInt(var))
  1492.                     {
  1493.                     case CK_REMOTE_DAEMON:
  1494.                         sprintf(tempStr, "%s\n", ND_UPDATE_PROCESSES);
  1495.                         SendSocketCommandLater(connection, tempStr);
  1496.                         ShowConnectionControls(connection, NULLOBJ, GetString(GetVar(connection, NAME)));
  1497.                         break;
  1498.                     case CK_LOCAL_DAEMON:
  1499.                         {
  1500.                         /*Make a local listener*/
  1501.                         NewListenerConnection();
  1502.                         }
  1503.                         break;
  1504.                     case CK_REMOTE_SCIAN:
  1505.                         /* say what kind of machine I am */
  1506. #if MACHINE == IRIS4D
  1507.                         sprintf(tempStr, "%s\n", NO_MESG_MACHINE_IRIS4D);
  1508. #else
  1509. #if MACHINE == RS6000
  1510.                         sprintf(tempStr, "%s\n", NO_MESG_MACHINE_RS6000);
  1511. #else
  1512.                         sprintf(tempStr, "%s\n", NO_MESG_MACHINE_UNKNOWN);
  1513. #endif
  1514. #endif
  1515.                         SendSocketCommandLater(connection, tempStr);
  1516.                         sprintf(tempStr, "%s\n", ND_LIST_OBJECTS);
  1517.                         SendSocketCommandLater(connection, tempStr);
  1518.                         break;
  1519.                     default:
  1520.                         ReportError("IdleConnection", "Internal Error: bad connection type");
  1521.                         break;
  1522.                     }
  1523.                 }
  1524.                 SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  1525.                 }
  1526.                 else
  1527.                 {
  1528.                 /*DIKEO make user alert*/
  1529.                 ReportError("IdleSockets", "Funny return");
  1530.                 SetConnectionState(connection, CS_MORIBUND);
  1531.                 ++TrashDayFlag;
  1532.                 }
  1533.             }
  1534.             }
  1535.         }
  1536.         else
  1537.         {
  1538.             ReportError("IdleSockets", "No socket file descriptor");
  1539.             SetConnectionState(connection, CS_MORIBUND);
  1540.             ++TrashDayFlag;
  1541.         }
  1542.         }
  1543.         break;
  1544.     case CS_WAIT_FOR_PASSWORD:            /*Waiting for a RUN? to come back*/
  1545.         {
  1546.         int sock;
  1547.         int nChars;
  1548.         ObjPtr command;
  1549.         ObjPtr curCmd;
  1550.  
  1551.         curCmd = GetVar(connection, CURCMD);
  1552.         if (!curCmd) curCmd = NewString(""); 
  1553.  
  1554.         sock = ((ConnectionPtr) connection) -> sock;
  1555.         if (sock >= 0)
  1556.         {
  1557.             Bool anything;
  1558.             char inChar;
  1559.             anything = false;
  1560.  
  1561.             /*See if there are characters waiting*/
  1562.             while ((1 == read(sock, &inChar, 1)) &&
  1563.                inChar &&
  1564.                !isspace(inChar))
  1565.             {
  1566.             char cmd[2];
  1567.             /*There's a command of some sort*/
  1568.             cmd[0] = inChar;
  1569.             cmd[1] = 0;
  1570.  
  1571.             curCmd = ConcatStrings(curCmd, NewString(cmd));
  1572.             anything = true;
  1573.             }
  1574.             if (anything)
  1575.             {
  1576.             SetVar(connection, CURCMD, curCmd);
  1577.             if (inChar == '\n' || inChar == 0)
  1578.             {
  1579.                 /* ignore it */
  1580.                 ((ConnectionPtr) connection) -> gotCmdEnd = true;
  1581.             }
  1582.             if (inChar == 0 || isspace(inChar))
  1583.             {
  1584.                 char *cmd;
  1585.  
  1586.                 /*The command is done.  Find it*/
  1587.                 cmd = GetString(curCmd);
  1588.                 if (strlen(cmd) == 4 && CMD(cmd) == CMD(ND_PASSWORD))
  1589.                 {
  1590.                 char *s;
  1591.                 ObjPtr var;
  1592.                 /*Got a password.  Return a version.*/
  1593.  
  1594.                 sprintf(tempStr, "%s Scian %s\n", ND_INFO_VERSION, SCIANVERSION);
  1595.                 s = tempStr + 5;
  1596.                 while (*s)
  1597.                 {
  1598.                     if (*s == ' ') *s = '_';
  1599.                     ++s;
  1600.                 }
  1601.                 SendSocketCommandLater(connection, tempStr);
  1602.                 /* say what kind of machine I am */
  1603. #if MACHINE == IRIS4D
  1604.                 sprintf(tempStr, "%s\n", NO_MESG_MACHINE_IRIS4D);
  1605. #else
  1606. #if MACHINE == RS6000
  1607.                 sprintf(tempStr, "%s\n", NO_MESG_MACHINE_RS6000);
  1608. #else
  1609.                 sprintf(tempStr, "%s\n", NO_MESG_MACHINE_UNKNOWN);
  1610. #endif
  1611. #endif
  1612.                 SendSocketCommandLater(connection, tempStr);
  1613.                 SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  1614.                 }
  1615.                 else
  1616.                 {
  1617.                 /*DIKEO make user alert*/
  1618.                 ReportError("IdleSockets", "Funny return");
  1619.                 SetConnectionState(connection, CS_MORIBUND);
  1620.                 }
  1621.             }
  1622.             }
  1623.         }
  1624.         else
  1625.         {
  1626.             ReportError("IdleSockets", "No socket file");
  1627.             SetConnectionState(connection, CS_MORIBUND);
  1628.         }
  1629.         }
  1630.         break;
  1631.     case CS_IDLING:            /*At connection idle*/
  1632.         {
  1633.         int sock; /* socket file descriptor */
  1634.         sock = ((ConnectionPtr) connection) -> sock;
  1635.         if (sock >= 0)
  1636.         {
  1637.             char inChar;
  1638.             /*See if there's a character waiting*/
  1639.             if ((1 == read(sock, &inChar, 1)) &&
  1640.             isalpha(inChar))
  1641.             {
  1642.             char cmd[2];
  1643.             /*There's a command of some sort*/
  1644.             cmd[0] = inChar;
  1645.             cmd[1] = 0;
  1646.  
  1647.             SetVar(connection, CURCMD, NewString(cmd));
  1648.             SetConnectionState(connection, CS_FILL_CMD);
  1649.             retVal = true;
  1650.             }
  1651.             else
  1652.             {
  1653.             /*See if there are commands to be sent*/
  1654.             ObjPtr cmdQueue;
  1655.             cmdQueue = GetVar(connection, OUTPUTQUEUE);
  1656.             if (cmdQueue)
  1657.             {
  1658.                 ThingListPtr runner;
  1659.                 runner = LISTOF(cmdQueue);
  1660.                 while (runner)
  1661.                 {
  1662.                 if (!IsPublished(runner -> thing))
  1663.                 {
  1664.                     char *str;
  1665.                     str = GetString(runner -> thing);
  1666.                     if (str)
  1667.                     {
  1668. #ifdef DEBUG
  1669.                     fprintf(stderr, "Sending string: %s\n", str);
  1670. #endif
  1671.                              writen(sock, str, strlen(str));
  1672.                     }
  1673.                     else
  1674.                     {
  1675. #ifdef DEBUG
  1676.                     fprintf(stderr, "ERROR! null string in OUTPUTQUEUE\n");
  1677. #endif
  1678.                     }
  1679.                 }
  1680.                 else
  1681.                 {
  1682. #ifdef DEBUG
  1683.                     fprintf(stderr, "Sending object: 0x%x\n", runner -> thing);
  1684. #endif
  1685.                     TransmitObject(runner -> thing, connection, true);
  1686.                 }
  1687.                 runner = runner -> next;
  1688.                 }
  1689.                 SetVar(connection, OUTPUTQUEUE, NewList());
  1690.             }
  1691.             }
  1692.         }
  1693.         }
  1694.         break;
  1695.     case CS_FILL_CMD:            /*Filling command*/
  1696.         {
  1697.         int sock;
  1698.         int nChars;
  1699.         ObjPtr command;
  1700.         ObjPtr curCmd;
  1701.  
  1702.         curCmd = GetVar(connection, CURCMD);
  1703.         if (!curCmd) curCmd = NewString(""); 
  1704.  
  1705.         sock = ((ConnectionPtr) connection) -> sock;
  1706.         if (sock >= 0)
  1707.         {
  1708.             Bool anything;
  1709.             char inChar = 'x';
  1710.             anything = false;
  1711.  
  1712.             /*See if there are characters waiting*/
  1713.             while ((1 == read(sock, &inChar, 1)) &&
  1714.                inChar &&
  1715.                !isspace(inChar))
  1716.             {
  1717.             char cmd[2];
  1718.             /*There's a command of some sort*/
  1719.             cmd[0] = inChar;
  1720.             cmd[1] = 0;
  1721.  
  1722.             curCmd = ConcatStrings(curCmd, NewString(cmd));
  1723.             anything = true;
  1724.             }
  1725.             SetVar(connection, CURCMD, curCmd);
  1726.             if (inChar == '\n' || inChar == 0)
  1727.             {
  1728.             ((ConnectionPtr) connection) -> gotCmdEnd = true;
  1729.             }
  1730.             if (inChar == 0 || isspace(inChar))
  1731.             {
  1732.             /*The command is done.  Find it*/
  1733.             FindCommand(connection);
  1734.             }
  1735.         }
  1736.         }
  1737.         retVal = true;
  1738.         break;
  1739.     case CS_READ_NUMBER_ONE:        /*Read first number*/
  1740.     case CS_READ_NUMBER_TWO:        /*Read second number*/
  1741.     case CS_READ_NUMBER_THREE:        /*Read third number*/
  1742.     case CS_READ_NUMBER_FOUR:        /*Read fourth number*/
  1743.         {
  1744.         int sock;
  1745.         int oldState;
  1746.  
  1747.         oldState = state;
  1748.  
  1749.         sock = ((ConnectionPtr) connection) -> sock;
  1750.         if (sock >= 0)
  1751.         {
  1752.             unsigned long num;
  1753.             Bool someDigits = false;
  1754.             char inChar;
  1755.             ObjPtr var;
  1756.  
  1757.             /*Get process num.  If null, it means that one hasn't been
  1758.               set yet, and leading spaces should be tolerated.*/
  1759.  
  1760.             switch (oldState)
  1761.             {
  1762.             case CS_READ_NUMBER_ONE:
  1763.                 var = GetVar(connection, READNUMBERONE);
  1764.                 break;
  1765.             case CS_READ_NUMBER_TWO:
  1766.                 var = GetVar(connection, READNUMBERTWO);
  1767.                 break;
  1768.             case CS_READ_NUMBER_THREE:
  1769.                 var = GetVar(connection, READNUMBERTHREE);
  1770.                 break;
  1771.             case CS_READ_NUMBER_FOUR:
  1772.                 var = GetVar(connection, READNUMBERFOUR);
  1773.                 break;
  1774.             default:
  1775.                 ReportError("IdleConnection", "Internal state error");
  1776.                 break;
  1777.             }
  1778.             if (var)
  1779.             {
  1780.             num = GetInt(var);
  1781.             someDigits = true;
  1782.             }
  1783.             else
  1784.             {
  1785.             num = 0;
  1786.             }
  1787.  
  1788.             /*See if there's a character waiting*/
  1789.             while (1 == read(sock, &inChar, 1))
  1790.             {
  1791.             if (isspace(inChar) && (inChar != '\n') && !someDigits)
  1792.             {
  1793.                 
  1794.                 /*Just skip the blanks*/
  1795.             }
  1796.             else if (inChar >= '0' && inChar <= '9')
  1797.             {
  1798.                 someDigits = true;
  1799.                 num *= 10;
  1800.                 num += inChar - '0';
  1801.             }
  1802.             else
  1803.             {
  1804.                 /*This is the end of the number*/
  1805.                 ObjPtr cmdObj;
  1806.  
  1807.                 if (inChar == '\n' || inChar == '\0')
  1808.                 {
  1809.                 ((ConnectionPtr) connection) -> gotCmdEnd = true;
  1810.                 }
  1811.  
  1812.                 cmdObj = GetStringVar("IdleConnection", connection, CURCMD);
  1813.                 if (cmdObj)
  1814.                 {
  1815.                 char *cmd;
  1816.  
  1817.                 cmd = GetString(cmdObj);
  1818.                 if (CMD(cmd) == CMD(ND_INFO_LIVE_PROCESS))
  1819.                 {
  1820.                     SetVar(connection, CMDPROCSOCKET, NewInt(num));
  1821.                     SetConnectionState(connection, CS_READ_PROC_NAME);
  1822.                 }
  1823.                 else if (CMD(cmd) == CMD(ND_INFO_DEAD_PROCESS))
  1824.                 {
  1825.                     SetVar(connection, CMDPROCSOCKET, NewInt(num));
  1826.                     SetConnectionState(connection, CS_READ_PROC_NAME);
  1827.                 }
  1828.                 else if (CMD(cmd) == CMD(NO_MESG_SEND_OBJECT))
  1829.                 {
  1830.                     ObjPtr sendObject;
  1831.                     sendObject = FindPublishedObject(num);
  1832.                     if (sendObject)
  1833.                     {
  1834.                     SendObjectLater(connection, sendObject);
  1835.                     }
  1836.                     SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  1837.                 }
  1838.                 else if (CMD(cmd) == CMD(ND_REG_OBJECT))
  1839.                 {
  1840.                     ObjPtr process;
  1841.  
  1842.                     process = GetVar(connection, OWNERPROCESS);
  1843.                     if (process && num)
  1844.                     {
  1845.                     NetworkIDIsWaiting(process, num, true);
  1846.                     SetVar(process, REMOTECHCOUNT, NewInt(0));
  1847.                     }
  1848.                     SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  1849.                 }
  1850.                 else if (CMD(cmd) == CMD(NO_MESG_GETVAR))
  1851.                 {
  1852.                     /* HAK! don't know how to deal with this yet!*/
  1853.                     switch (oldState)
  1854.                     {
  1855.                     case CS_READ_NUMBER_ONE:
  1856.                         SetConnectionState(connection, CS_READ_NUMBER_TWO);
  1857.                         break;
  1858.                     case CS_READ_NUMBER_TWO:
  1859.                         {
  1860.                         ObjPtr obj, val;
  1861.                         int netid, valNetid;
  1862.  
  1863.                         netid = GetInt(GetIntVar("IdleConnection", connection, READNUMBERONE));
  1864.                         obj = FindPublishedObject(netid);
  1865.                         if (obj)
  1866.                         {
  1867.                             VarsPtr vPtr;
  1868.                             unsigned long chCt;
  1869.  
  1870.                             if (!ThisWouldBeAReallyBadThing) /* should not be necessary! */
  1871.                             MakeVar(obj, num);
  1872.                             val = GetVar(obj, num);
  1873.                             if (val)
  1874.                             {
  1875.                             valNetid = PublishObject(val);
  1876.                             }
  1877.                             else
  1878.                             {
  1879.                             valNetid = 0;
  1880.                             }
  1881.  
  1882.                             vPtr = GetVarNode(obj, num);
  1883.                             if (vPtr)
  1884.                             chCt = vPtr -> chCount;
  1885.                             else
  1886.                             chCt = 0;
  1887.  
  1888.                             sprintf(tempStr, "%s %ld %ld %ld %ld\n", NO_MESG_GOTVAR, netid, num, valNetid, chCt);
  1889.                             SendSocketCommandLater(connection, tempStr);
  1890.                         }
  1891.                         else
  1892.                         {
  1893. #if 1
  1894.                             sprintf(tempStr, "%s %ld %ld %ld %ld\n", NO_MESG_GOTVAR, netid, num, NETSTUBFLAG, 0);
  1895. #else
  1896.                             sprintf(tempStr, "%s %ld %ld %ld %ld\n", NO_MESG_GOTVAR, netid, num, 0, 0);
  1897. #endif
  1898.                             SendSocketCommandLater(connection, tempStr);
  1899.                         }
  1900.                         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  1901.                         }
  1902.                         break;
  1903.                     default:
  1904.                         ReportError("IdleConnection", "Internal State Error");
  1905.                         break;
  1906.                     }
  1907.                 }
  1908.                 else if (CMD(cmd) == CMD(NO_MESG_GETELEMENT))
  1909.                 {
  1910.                     switch (oldState)
  1911.                     {
  1912.                     case CS_READ_NUMBER_ONE:
  1913.                         SetConnectionState(connection, CS_READ_NUMBER_TWO);
  1914.                         break;
  1915.                     case CS_READ_NUMBER_TWO:
  1916.                         {
  1917.                         ObjPtr obj, el, *elements;
  1918.                         int netid, elNetid;
  1919.  
  1920.                         netid = GetInt(GetIntVar("IdleConnection", connection, READNUMBERONE));
  1921.                         obj = FindPublishedObject(netid);
  1922.                         if (obj)
  1923.                         {
  1924.                             elements = (ObjPtr *) ELEMENTS(obj);
  1925.                             el = elements[num];
  1926.                             if (el)
  1927.                             {
  1928.                             elNetid = PublishObject(el);
  1929.                             }
  1930.                             else
  1931.                             {
  1932.                             elNetid = 0;
  1933.                             }
  1934.                             sprintf(tempStr, "%s %d %d %d\n", NO_MESG_GOTELEMENT, netid, num, elNetid);
  1935.                             SendSocketCommandLater(connection, tempStr);
  1936.                         }
  1937.                         else
  1938.                         {
  1939.                             sprintf(tempStr, "%s %d %d %d\n", NO_MESG_GOTELEMENT, netid, num, 0);
  1940.                             SendSocketCommandLater(connection, tempStr);
  1941.                         }
  1942.                         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  1943.                         }
  1944.                         break;
  1945.                     default:
  1946.                         ReportError("IdleConnection", "Internal State Error");
  1947.                         break;
  1948.                     }
  1949.                 }
  1950.                 else if (CMD(cmd) == CMD(NO_MESG_GOTVAR))
  1951.                 {
  1952.                     switch (oldState)
  1953.                     {
  1954.                     case CS_READ_NUMBER_ONE:
  1955.                         SetConnectionState(connection, CS_READ_NUMBER_TWO);
  1956.                         break;
  1957.                     case CS_READ_NUMBER_TWO:
  1958.                         SetConnectionState(connection, CS_READ_NUMBER_THREE);
  1959.                         break;
  1960.                     case CS_READ_NUMBER_THREE:
  1961.                         SetConnectionState(connection, CS_READ_NUMBER_FOUR);
  1962.                         break;
  1963.                     case CS_READ_NUMBER_FOUR:
  1964.                         if (GetInt(GetVar(connection, READNUMBERTHREE))) /* num3 = 0 means it was a null object */
  1965.                         {
  1966.                         ObjPtr process, target, value;
  1967.  
  1968.                         process = GetObjectVar("IdleConnection", connection, OWNERPROCESS);
  1969.                         target = FindRemoteObject(process, GetInt(GetVar(connection, READNUMBERONE)), false); /* MUST be false! */
  1970. if (!target)
  1971.     fprintf(stderr, "No Target\n");
  1972.  
  1973. #if 1 /* HAS to be this way to prevent overlaid calls to WaitForNetObject[Var] and IdleConnection */
  1974.                         {
  1975.                             VarsPtr vptr;
  1976.  
  1977.                             if (NETSTUBFLAG == GetInt(GetVar(connection, READNUMBERTHREE)))
  1978.                             {
  1979. fprintf(stderr, "Very bad!\n");
  1980.                             /* other guy couldn't find this target! */
  1981.                             target -> flags = target -> flags | ISDEFUNCT;
  1982.                             }
  1983.  
  1984. /* HAK shouldn't have to do this */            /* SendSendObjectMessage(connection, GetInt(GetVar(connection, READNUMBERTHREE))); */
  1985. /* correct? */
  1986.                             vptr = GetVarNode(target, GetInt(GetVar(connection, READNUMBERTWO)));
  1987.                             if (!vptr)
  1988.                             {
  1989.                             SetVar(target, GetInt(GetIntVar("IdleConnection", connection, READNUMBERTWO)), value);
  1990.                             vptr = GetVarNode(target, GetInt(GetVar(connection, READNUMBERTWO)));
  1991.                             }
  1992.                             vptr -> remoteNetID = GetInt(GetVar(connection, READNUMBERTHREE));
  1993.                             vptr -> remoteChCount = num;
  1994.                             vptr -> value = NULLOBJ;
  1995.                         }
  1996. #else
  1997.                         value = FindRemoteObject(process, GetInt(GetVar(connection, READNUMBERTHREE)), false);
  1998.                         if (!value)
  1999.                         {
  2000.                             /* ReportError("IdleConnection", "Something smells bad in Sioux City\n"); */
  2001.                         }
  2002.                         else
  2003.                         {
  2004.                             VarsPtr vPtr;
  2005.                             SetVar(target, GetInt(GetIntVar("IdleConnection", connection, READNUMBERTWO)), value);
  2006.                             vPtr = GetVarNode(target, GetInt(GetVar(connection, READNUMBERTWO)));
  2007.                             vPtr -> remoteNetID = GetInt(GetVar(connection, READNUMBERTHREE));
  2008.                             vPtr -> remoteChCount = num;
  2009.                             vPtr -> value = value;
  2010.                         }
  2011. #endif
  2012.                         }
  2013.                         else
  2014.                         {
  2015.                         ObjPtr process, target;
  2016.                         process = GetObjectVar("IdleConnection", connection, OWNERPROCESS);
  2017.                         target = FindRemoteObject(process, GetInt(GetVar(connection, READNUMBERONE)), false); /* MUST be false! */
  2018. if (!target)
  2019.     fprintf(stderr, "No Target\n");
  2020.                         SetVar(target, GetInt(GetVar(connection, READNUMBERTWO)), NULLOBJ);
  2021.                         }
  2022.                         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  2023.                         break;
  2024.                     default:
  2025.                         ReportError("IdleConnection", "Internal State Error");
  2026.                         break;
  2027.                     }
  2028.                 }
  2029.                 else if (CMD(cmd) == CMD(NO_MESG_GOTELEMENT))
  2030.                 {
  2031.                     switch (oldState)
  2032.                     {
  2033.                     case CS_READ_NUMBER_ONE:
  2034.                         SetConnectionState(connection, CS_READ_NUMBER_TWO);
  2035.                         break;
  2036.                     case CS_READ_NUMBER_TWO:
  2037.                         SetConnectionState(connection, CS_READ_NUMBER_THREE);
  2038.                         break;
  2039.                     case CS_READ_NUMBER_THREE:
  2040. #if 0
  2041.                         /* old code */
  2042.                         if (num) /* num = 0 means it was a null object */
  2043.                         {
  2044.                         sprintf(tempStr, "%s %d\n", NO_MESG_SEND_OBJECT, num);
  2045.                         SendSocketCommandLater(connection, tempStr);
  2046.                         If we do this, MUST do a NetworkIDISWaiting!
  2047.                         }
  2048. #else
  2049.                         /* SPECIAL CASE: if obj netid == element's netid, there's no object coming */
  2050.                         {
  2051.                         ObjPtr process;
  2052.  
  2053.                         process = GetVar(connection, OWNERPROCESS);
  2054.                         if (process)
  2055.                         {
  2056.                             ObjPtr target, *elements;
  2057.                             unsigned long offset;
  2058.  
  2059.                             /* these are always integers, I hope */
  2060.                             target = FindRemoteObject(process, GetInt(GetVar(connection, READNUMBERONE)), false); /* MUST be false! */
  2061. if (!target)
  2062.     fprintf(stderr, "No Target!\n");
  2063. if (!IsObjArray(target))
  2064.     fprintf(stderr, "Not an ObjArray!\n");
  2065.                             elements = (ObjPtr *) ELEMENTS(target);
  2066.                             offset = GetInt(GetVar(connection, READNUMBERTWO));
  2067.                             elements[offset] = (ObjPtr) num;
  2068.                         }
  2069.                         }
  2070. #endif
  2071.                         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  2072.                         break;
  2073.                     default:
  2074.                         ReportError("IdleConnection", "Internal State Error");
  2075.                         break;
  2076.                     }
  2077.                 }
  2078. #ifndef NEWSTYLEUPDATES
  2079.                 else if (CMD(cmd) == CMD(NO_MESG_UPDATEVAR))
  2080.                 {
  2081.                     switch(oldState)
  2082.                     {
  2083.                     case CS_READ_NUMBER_ONE:
  2084.                         SetConnectionState(connection, CS_READ_NUMBER_TWO);
  2085.                         break;
  2086.                     case CS_READ_NUMBER_TWO:
  2087.                         {
  2088.                         ObjPtr process;
  2089.                         process = GetVar(connection, OWNERPROCESS);
  2090.                         if (process)
  2091.                         {
  2092.                             ObjPtr object;
  2093.                             object = FindRemoteObject(process, GetInt(GetVar(connection, READNUMBERONE)), false);
  2094.                             if (object)
  2095.                             {
  2096.                             VarsPtr vptr;
  2097.  
  2098.                             SetVar(object, num, NULLOBJ);
  2099.                             vptr = GetVarNode(object, num);
  2100.                             vptr -> process = process;
  2101.                             vptr -> remoteNetID = NETSTUBFLAG;
  2102.                             vptr -> remoteChCount = anotherDamnReferenceCount;
  2103. /* NOT!                            SendGetVarMessage(object, num);
  2104. */
  2105.                             }
  2106.                             if (num == DATA)
  2107.                             {
  2108.                             DatasetChanged(object);
  2109.                             }
  2110.  
  2111.                         }
  2112.                         }
  2113.                         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  2114.                         break;
  2115.                     default:
  2116.                         ReportError("IdleConnection", "Internal State Error");
  2117.                         break;
  2118.                     }
  2119.                 }
  2120. #else
  2121.                 /* "UPV2 netid varname valuenetid varchct " */
  2122.                 else if (CMD(cmd) == CMD(NO_MESG_UPDATEVAR_ID))
  2123.                 {
  2124.                     switch(oldState)
  2125.                     {
  2126.                     case CS_READ_NUMBER_ONE:
  2127.                         SetConnectionState(connection, CS_READ_NUMBER_TWO);
  2128.                         break;
  2129.                     case CS_READ_NUMBER_TWO:
  2130.                         SetConnectionState(connection, CS_READ_NUMBER_THREE);
  2131.                         break;
  2132.                     case CS_READ_NUMBER_THREE:
  2133.                         SetConnectionState(connection, CS_READ_NUMBER_FOUR);
  2134.                         break;
  2135.                     case CS_READ_NUMBER_FOUR:
  2136.                         {
  2137.                         ObjPtr process;
  2138.                         process = GetVar(connection, OWNERPROCESS);
  2139.                         if (process)
  2140.                         {
  2141.                             ObjPtr object;
  2142.                             object = FindRemoteObject(process, GetInt(GetVar(connection, READNUMBERONE)), false);
  2143.                             if (object)
  2144.                             {
  2145.                             VarsPtr vptr;
  2146.                             ObjPtr value;
  2147.  
  2148.                             value = FindRemoteObject(process, GetInt(GetVar(connection, READNUMBERTHREE)), false);
  2149.                             if (value)
  2150.                             {
  2151.                                 fprintf(stderr, "not good.. got UPDATEVAR_ID but I don't have netid %ld\n",  GetInt(GetVar(connection, READNUMBERTHREE)));
  2152.                                 SetVar(object, GetInt(GetVar(connection, READNUMBERTWO)), value);
  2153.                             }
  2154.                             vptr = GetVarNode(object, GetInt(GetVar(connection, READNUMBERTWO)));
  2155.                             if (!vptr)
  2156.                             {
  2157.                                 SetVar(object, GetInt(GetVar(connection, READNUMBERTWO)), NULLOBJ);
  2158.                                 vptr = GetVarNode(object, GetInt(GetVar(connection, READNUMBERTWO)));
  2159.                             }
  2160.                             vptr -> process = process;
  2161.                             vptr -> remoteNetID = GetInt(GetVar(connection, READNUMBERTHREE));
  2162.                             vptr -> remoteChCount = num;
  2163. /* NOT!                            SendGetVarMessage(object, GetInt(GetVar(connection, READNUMBERTWO)));
  2164. */
  2165.                             }
  2166.                             if (GetInt(GetVar(connection, READNUMBERTWO)) == DATA)
  2167.                             {
  2168.                             DatasetChanged(object);
  2169.                             }
  2170.  
  2171.                         }
  2172.                         }
  2173.                         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  2174.                         break;
  2175.                     default:
  2176.                         ReportError("IdleConnection", "Internal State Error");
  2177.                         break;
  2178.                     }
  2179.                 }
  2180.                 /* "UPV3 netid varname valnetid varchct ... (obj follows) (currently in separate msg) */
  2181.                 else if (CMD(cmd) == CMD(NO_MESG_UPDATEVAR_SEND))
  2182.                 {
  2183.                     switch(oldState)
  2184.                     {
  2185.                     case CS_READ_NUMBER_ONE:
  2186.                         SetConnectionState(connection, CS_READ_NUMBER_TWO);
  2187.                         break;
  2188.                     case CS_READ_NUMBER_TWO:
  2189.                         SetConnectionState(connection, CS_READ_NUMBER_THREE);
  2190.                         break;
  2191.                     case CS_READ_NUMBER_THREE:
  2192.                         SetConnectionState(connection, CS_READ_NUMBER_FOUR);
  2193.                         break;
  2194.                     case CS_READ_NUMBER_FOUR:
  2195.                         {
  2196.                         ObjPtr process;
  2197.                         process = GetVar(connection, OWNERPROCESS);
  2198.                         if (process)
  2199.                         {
  2200.                             ObjPtr object;
  2201.                             object = FindRemoteObject(process, GetInt(GetVar(connection, READNUMBERONE)), false);
  2202.                             if (object)
  2203.                             {
  2204.                             VarsPtr vptr;
  2205.  
  2206.                             SetVar(object, GetInt(GetVar(connection, READNUMBERTWO)), NULLOBJ);
  2207.                             vptr = GetVarNode(object, GetInt(GetVar(connection, READNUMBERTWO)));
  2208.                             vptr -> process = process;
  2209.                             vptr -> remoteNetID = NETSTUBFLAG;
  2210.                             vptr -> remoteChCount = anotherDamnReferenceCount;
  2211.                             }
  2212.                             if (GetInt(GetVar(connection, READNUMBERTWO)) == DATA)
  2213.                             {
  2214.                             DatasetChanged(object);
  2215.                             }
  2216.                             NetworkIDIsWaiting(process, GetInt(GetVar(connection, READNUMBERTHREE)), true);
  2217.                         }
  2218.                         }
  2219.                         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  2220.                         break;
  2221.                     default:
  2222.                         ReportError("IdleConnection", "Internal State Error");
  2223.                         break;
  2224.                     }
  2225.                 }
  2226. #endif
  2227.                 else
  2228.                 {
  2229.                     ReportError("IdleConnection", "Funny command in CS_READ_NUMBER_num");
  2230.                     SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  2231.                 }
  2232.                 }
  2233.                 break; /* out of while loop */
  2234.             }
  2235.             }
  2236.             if (someDigits)
  2237.             {
  2238.             switch (oldState)
  2239.             {
  2240.                 case CS_READ_NUMBER_ONE:
  2241.                 var = SetVar(connection, READNUMBERONE, NewInt(num));
  2242.                 break;
  2243.                 case CS_READ_NUMBER_TWO:
  2244.                 var = SetVar(connection, READNUMBERTWO, NewInt(num));
  2245.                 break;
  2246.                 case CS_READ_NUMBER_THREE:
  2247.                 var = SetVar(connection, READNUMBERTHREE, NewInt(num));
  2248.                 break;
  2249.                 case CS_READ_NUMBER_FOUR:
  2250.                 var = SetVar(connection, READNUMBERFOUR, NewInt(num));
  2251.                 break;
  2252.                 default:
  2253.                 ReportError("IdleConnection", "Internal state error");
  2254.                 break;
  2255.             }
  2256.             }
  2257.         }
  2258.         }
  2259.         retVal = true;
  2260.         break;
  2261.     case CS_READ_PROC_NAME:            /*Read the proc name*/
  2262.         {
  2263.         int sock;
  2264.  
  2265.         sock = ((ConnectionPtr) connection) -> sock;
  2266.         if (sock)
  2267.         {
  2268.             Bool someAlpha = false;        /*True iff there's some alpha*/
  2269.             char inChar;
  2270.             Bool escaped;
  2271.             ObjPtr var;
  2272.  
  2273.             var = GetVar(connection, CMDPROCNAME);
  2274.             if (var)
  2275.             {
  2276.             someAlpha = true;
  2277.             }
  2278.  
  2279.             escaped = GetPredicate(connection, ESCAPED);
  2280.  
  2281.             /*See if there's a character waiting*/
  2282.             while ((1 == read(sock, &inChar, 1)))
  2283.             {
  2284.             if (!escaped && !someAlpha && (inChar != '\n') && isspace(inChar))
  2285.             {
  2286.                 /*Just skip the blanks*/
  2287.             }
  2288.             else if (!escaped && (inChar == 0 || inChar == '\n'))
  2289.             {
  2290.                 ObjPtr cmdObj;
  2291.              
  2292.                 /*This is the end of the name*/
  2293.                 cmdObj = GetStringVar("IdleConnection", connection, CURCMD);
  2294.                 if (cmdObj)
  2295.                 {
  2296.                 char *cmd;
  2297.                 cmd = GetString(cmdObj);
  2298.                 if (CMD(cmd) == CMD(ND_INFO_LIVE_PROCESS))
  2299.                 {
  2300.                     NewProcess(connection, GetString(var), GetInt(GetVar(connection, CMDPROCSOCKET)));
  2301.                 }
  2302.                 else if (CMD(cmd) == CMD(ND_INFO_DEAD_PROCESS))
  2303.                 {
  2304.                     DeleteProcess(connection, GetInt(GetVar(connection, CMDPROCSOCKET)));
  2305.                 }
  2306.                 }
  2307.                 SetConnectionState(connection, CS_IDLING);
  2308.                 break;
  2309.             }
  2310.             else if (!escaped && (inChar == '\\'))
  2311.             {
  2312.                 SetVar(connection, ESCAPED, ObjTrue);
  2313.                 escaped = true;
  2314.             }
  2315.             else
  2316.             {
  2317.                 char s[2];
  2318.  
  2319.                 if (escaped)
  2320.                 {
  2321.                 SetVar(connection, ESCAPED, ObjFalse);
  2322.                 }
  2323.                 else if (inChar == '_')
  2324.                 {
  2325.                 inChar = ' ';
  2326.                 }
  2327.  
  2328.                 s[0] = inChar;
  2329.                 s[1] = 0;
  2330.  
  2331.                 if (var)
  2332.                 {
  2333.                 var = ConcatStrings(var, NewString(s));
  2334.                 }
  2335.                 else
  2336.                 {
  2337.                 var = NewString(s);
  2338.                 someAlpha = true;
  2339.                 }
  2340.             }
  2341.             }
  2342.             if (someAlpha)
  2343.             {
  2344.             SetVar(connection, CMDPROCNAME, var);
  2345.             }
  2346.         }
  2347.         }
  2348.         break;
  2349.     case CS_READ_OBJECT:
  2350.         {
  2351.         ObjPtr filledObj, process;
  2352.         unsigned long chCt;
  2353.  
  2354.         process = GetObjectVar ("IdleConnection", connection, OWNERPROCESS);
  2355.         chCt = GetInt(GetIntVar("IdleConnection", process, REMOTECHCOUNT));
  2356.         filledObj = ReceiveObject(connection, chCt); /* currently, wait until obj is filled */
  2357. #ifdef DEBUG
  2358. if (filledObj)
  2359.    fprintf(stderr, "well, it returned something\n");
  2360. else
  2361.    fprintf(stderr, "ERROR! ReceiveObject didn't return anything!\n");
  2362. #endif
  2363.         if (filledObj)
  2364.         {
  2365.             ObjPtr allObjects;
  2366.             int varnum;
  2367.  
  2368.             allObjects = GetVar(process, ALLOBJECTS);
  2369.             if (!allObjects)
  2370.             {
  2371.             allObjects = NewList();
  2372.             }
  2373.             PrefixList(allObjects, filledObj);
  2374.  
  2375.             SetVar(process, ALLOBJECTS, allObjects);
  2376.  
  2377.             if (IsRemoteAdvertised(filledObj))
  2378.             {
  2379.             /* must be a top-level advertised object */
  2380.             ObjPtr allAdvertised;
  2381.  
  2382.             allAdvertised = GetVar(process, ALLADVERTISED);
  2383.             if (!allAdvertised)
  2384.             {
  2385.                 allAdvertised = NewList();
  2386.             }
  2387.             PrefixList(allAdvertised, filledObj);
  2388.             SetVar(process, ALLADVERTISED, allAdvertised);
  2389.             SetMethod(filledObj, NEWREMOTEOBJ, NewRemoteObject);
  2390.             DeferMessage(filledObj, NEWREMOTEOBJ);
  2391.             }
  2392.             else
  2393.             {
  2394.             /* Do nothing. Really! */
  2395.             }
  2396.         }
  2397.         else
  2398.         {
  2399. fprintf(stderr, "I guess the connection didn't have an owner process\n");
  2400.         }
  2401.  
  2402.         SetConnectionState(connection, CS_WAIT_FOR_CMD_END);
  2403.         }
  2404.         retVal = true;
  2405.         break;
  2406.     case CS_WAIT_FOR_CMD_END:        /*Wait for the end of the command*/
  2407.         {
  2408.         int sock;
  2409.  
  2410.         sock = ((ConnectionPtr) connection) -> sock;
  2411.         if (((ConnectionPtr) connection) -> gotCmdEnd)
  2412.         {
  2413.             SetVar(connection, CURCMD, NULLOBJ);
  2414.             SetConnectionState(connection, CS_IDLING);
  2415.         }
  2416.         else if (sock)
  2417.         {
  2418.             char inChar = 'x';
  2419.             /*See if there's a character waiting*/
  2420.             while ((1 == read(sock, &inChar, 1)))
  2421.             {
  2422.             if (inChar == '\n' || inChar == 0)
  2423.             {
  2424.                 SetVar(connection, CURCMD, NULLOBJ);
  2425.                 SetConnectionState(connection, CS_IDLING);
  2426.                 break;
  2427.             }
  2428.             }
  2429.         }
  2430.         ((ConnectionPtr) connection) -> gotCmdEnd = false;
  2431.         }
  2432.         retVal = true;
  2433.         break;
  2434.     case CS_MORIBUND:            /*Moribund.  Kill connection*/
  2435.         KillConnection(connection);
  2436.         break;
  2437.     case CS_LIMBO:                /*Process is in limbo.  Do nothing and let idle expire.*/
  2438.         break;
  2439.     default:
  2440.         fprintf(stderr, "Funny state in IdleConnection\n");
  2441.         break;
  2442.     }
  2443. #ifdef PARANOID
  2444.     --ICCount;
  2445. #endif
  2446.     return retVal;
  2447. }
  2448.  
  2449. /* returns true IFF all connections are in idle state, and have no queued
  2450.  * output waiting. If flag == true, prints the reason it's returning false
  2451.  */
  2452. #ifdef PROTO
  2453. Bool AllConnectionsIdle(Bool flag)
  2454. #else
  2455. Bool AllConnectionsIdle(flag)
  2456. Bool flag;
  2457. #endif
  2458. {
  2459.     ThingListPtr runner;
  2460.     int state;
  2461.     ObjPtr cmdQ;
  2462.  
  2463.     runner = LISTOF(allConnections);
  2464.     while (runner)
  2465.     {
  2466.     state = GetConnectionState(runner -> thing);
  2467.     if (state != CS_IDLING && state != CS_MORIBUND && state != CS_LIMBO && state != CS_LISTENING)
  2468.     {
  2469.         if (flag)
  2470.         fprintf(stderr, "found connection in state %s\n", stateName[state]);
  2471.         return false;
  2472.     }
  2473.     else if (state == CS_IDLING || state == CS_LIMBO)
  2474.     {
  2475.         cmdQ = GetVar(runner -> thing, OUTPUTQUEUE);
  2476.         if (cmdQ)
  2477.         {
  2478.         /* if there's something waiting in the queue, it's not idle */
  2479.         if (LISTOF(cmdQ))
  2480.         {
  2481.             if (flag)
  2482.             fprintf(stderr, "found pending output in socket in state %s\n", stateName[state]);
  2483.             return false;
  2484.         }
  2485.         }
  2486.     }
  2487.     runner = runner -> next;
  2488.     }
  2489.     return true;
  2490. }
  2491.  
  2492. #if 0
  2493. #ifdef PROTO
  2494. Bool IdleAllConnections(void)
  2495. #else
  2496. void IdleAllConnections()
  2497. #endif
  2498. /*Idles all the connections*/
  2499. {
  2500.     ThingListPtr runner;
  2501.     Bool retVal;
  2502.  
  2503.     retVal = false;
  2504.     runner = LISTOF(allConnections);
  2505.     while (runner)
  2506.     {
  2507.     retVal = retVal || IdleConnection(runner -> thing);
  2508.     runner = runner -> next;
  2509.     }
  2510.     return retVal;
  2511. }
  2512. #else
  2513. #ifdef PROTO
  2514. Bool IdleAllConnections(void)
  2515. #else
  2516. void IdleAllConnections()
  2517. #endif
  2518. /*Idles all the connections*/
  2519. {
  2520.     ThingListPtr runner;
  2521.     Bool retVal;
  2522.  
  2523.     retVal = true;
  2524.     while (retVal) /* keep going until all connections return false */
  2525.     {
  2526.     retVal = false;
  2527.     runner = LISTOF(allConnections);
  2528.     while (runner)
  2529.     {
  2530.     retVal = retVal || IdleConnection(runner -> thing);
  2531.     runner = runner -> next;
  2532.     }
  2533.     }
  2534.     return retVal;
  2535. }
  2536. #endif
  2537.  
  2538. #ifdef PROTO
  2539. static ObjPtr NewConnection(char *machineName, int connectionKind)
  2540. #else
  2541. static ObjPtr NewConnection(machineName, connectionKind)
  2542. char *machineName;
  2543. Bool connectionKind;
  2544. #endif
  2545. /*Makes a new connection to machine machineName.  connectionKind
  2546.   is the kind of connection:
  2547.     CK_REMOTE_DAEMON    Connection to a remote network daemon
  2548.     CK_LOCAL_DAEMON        Connection to a local daemon
  2549.     CK_LISTENING_SCIAN    Listening connection on a local SciAn
  2550.     CK_REMOTE_SCIAN        Connection to a remote SciAn (not implemented)
  2551.     CK_LOCAL_SCIAN        Connection from a local SciAn (not implemented)
  2552.  
  2553.   Does not do kind-specific initialization for the connection, such
  2554.   as socket ID, and leaves the connection in limbo.
  2555. */
  2556. {
  2557.     char *s;
  2558.     ObjPtr connection;
  2559.  
  2560.     /*Stuff this in lastComputer*/
  2561.     if (lastComputer)
  2562.     {
  2563.     Free(lastComputer);
  2564.     }
  2565.     lastComputer = Alloc(strlen(machineName) + 1);
  2566.     strcpy(lastComputer, machineName);
  2567.  
  2568.     /*Create the new connection*/
  2569.     connection = NewObject(connectionClass, sizeof(Connection) - sizeof(Thing));
  2570.     SetVar(connection, CONNECTIONKIND, NewInt(connectionKind));
  2571.     SETOBJTYPE(connection -> flags, CONNECTION);
  2572.     ((ConnectionPtr) connection) -> sock = -1;
  2573.     ((ConnectionPtr) connection) -> gotCmdEnd = false;
  2574.     ((ConnectionPtr) connection) -> template = -1;
  2575.  
  2576.     PrefixList(allConnections, connection);
  2577.  
  2578.     SetVar(connection, NAME, NewString(machineName));
  2579.     SetVar(connection, OUTPUTQUEUE, NewList());
  2580.     SetVar(connection, ALLPROCESSES, NewList());
  2581.  
  2582.     SetVar(connection, CONNECTIONSTATE, NewInt(CS_LIMBO));
  2583.  
  2584.     return connection;
  2585. }
  2586.  
  2587. #ifdef PROTO
  2588. ObjPtr NewLocalDaemonConnection(void)
  2589. #else
  2590. ObjPtr NewLocalDaemonConnection()
  2591. #endif
  2592. /*Make a new connection to the local daemon*/
  2593. {
  2594.     char hostName[200];
  2595.     ThingListPtr runner;
  2596.     ObjPtr retVal;
  2597.  
  2598.     /*See if there's connection to the daemon already*/
  2599.     runner = LISTOF(allConnections);
  2600.     while (runner)
  2601.     {
  2602.     ObjPtr var;
  2603.     var = GetIntVar("NewLocalDaemonConnection", runner -> thing, CONNECTIONKIND);
  2604.     if (var && GetInt(var) == CK_LOCAL_DAEMON)
  2605.     {
  2606.         return runner -> thing;
  2607.     }
  2608.     runner = runner -> next;
  2609.     }
  2610.  
  2611.     /*There must not be.*/
  2612.     gethostname(hostName, 199);
  2613.     hostName[199] = 0;
  2614.     retVal = NewConnection(hostName, CK_LOCAL_DAEMON);
  2615.     SetConnectionState(retVal, CS_NAME_ONLY);
  2616.     return retVal;
  2617. }
  2618.  
  2619. #ifdef PROTO
  2620. ObjPtr NewRemoteDaemonConnection(char *hostName)
  2621. #else
  2622. ObjPtr NewRemoteDaemonConnection(hostName)
  2623. char *hostName;
  2624. #endif
  2625. /*Make a new connection to the daemon on hostName*/
  2626. {
  2627.     ObjPtr retVal;
  2628.  
  2629.     retVal = NewConnection(hostName, CK_REMOTE_DAEMON);
  2630.     SetVar(retVal, SOCKETID, NewInt(ND_BASE_SOCKET_NUMBER));
  2631.     SetConnectionState(retVal, CS_NAME_ONLY);
  2632.     return retVal;
  2633. }
  2634.  
  2635. #ifdef PROTO
  2636. ObjPtr NewRemoteScianConnection(char *hostName, int port, ObjPtr process)
  2637. #else
  2638. ObjPtr NewRemoteScianConnection(hostName, port, process)
  2639. char *hostName;
  2640. int port
  2641. ObjPtr process;
  2642. #endif
  2643. /*Make a new connection to the SciAn on hostName on socket port*/
  2644. {
  2645.     ObjPtr retVal;
  2646.  
  2647.     retVal = NewConnection(hostName, CK_REMOTE_SCIAN);
  2648.     SetVar(retVal, SOCKETID, NewInt(port));
  2649.     SetConnectionState(retVal, CS_NAME_ONLY);
  2650.     SetVar(retVal, OWNERPROCESS, process); /* JRM connection needs assoc. proc. */
  2651.     return retVal;
  2652. }
  2653.  
  2654.  
  2655. #ifdef PROTO
  2656. static ObjPtr NewListenerConnection(void)
  2657. #else
  2658. static ObjPtr NewListenerConnection();
  2659. #endif
  2660. {
  2661.     ObjPtr retVal;
  2662.     ThingListPtr runner;
  2663.  
  2664.     /*See if there's connection to the daemon already*/
  2665.     runner = LISTOF(allConnections);
  2666.     while (runner)
  2667.     {
  2668.     ObjPtr var;
  2669.     var = GetIntVar("NewListenerConnection", runner -> thing, CONNECTIONKIND);
  2670.     if (var && GetInt(var) == CK_LISTENING_SCIAN)
  2671.     {
  2672.         return runner -> thing;
  2673.     }
  2674.     runner = runner -> next;
  2675.     }
  2676.  
  2677.     retVal = NewConnection("", CK_LISTENING_SCIAN);
  2678.  
  2679.     SetConnectionState(retVal, CS_NOT_LISTENING);
  2680.     return retVal;
  2681. }
  2682.  
  2683. #ifdef PROTO
  2684. static ObjPtr NewLocalScianConnection(int file)
  2685. #else
  2686. static ObjPtr NewLocalScianConnection(file)
  2687. int file;
  2688. #endif
  2689. /*Opens a new local Scian connection using file as descriptor*/
  2690. {
  2691.     ObjPtr retVal = NULLOBJ;
  2692.  
  2693.     if (file >= 0)
  2694.     {
  2695.     retVal = NewConnection("", CK_LOCAL_SCIAN);
  2696.     ((ConnectionPtr) retVal) -> sock = file;
  2697.     SetConnectionState(retVal, CS_WAIT_FOR_PASSWORD);
  2698.     }
  2699.     else
  2700.     {
  2701.     ReportError("NewLocalScianConnection", "bad file descriptor");
  2702.     retVal = NULLOBJ;
  2703.     }
  2704.     return retVal;
  2705. }
  2706.  
  2707. static ObjPtr ConnectToProcess(process)
  2708. ObjPtr process;
  2709. /*Method to connect to a process*/
  2710. {
  2711.     ThingListPtr runner;
  2712.     ObjPtr ownerConnection;
  2713.     ObjPtr connection = NULLOBJ;
  2714.     ObjPtr var;
  2715.     char *name;
  2716.     int port;
  2717.  
  2718.     /*First see if there is already a process in connection*/
  2719.     runner = LISTOF(allConnections);
  2720.     while (runner)
  2721.     {
  2722.     if (GetVar(runner -> thing, OWNERPROCESS) == process)
  2723.     {
  2724.         connection = runner -> thing;
  2725.         break;
  2726.     }
  2727.     runner = runner -> next;
  2728.     }
  2729.  
  2730.     if (!connection)
  2731.     {
  2732.     /*Have to make the connection.  Get machine name from owner connection*/
  2733.     ownerConnection = GetVar(process, OWNERCONNECTION);
  2734.     if (!ownerConnection)
  2735.     {
  2736.         return ObjFalse;
  2737.     }
  2738.  
  2739.     var = GetStringVar("ConnectToProcess", ownerConnection, NAME);
  2740.     if (!var)
  2741.     {
  2742.         return ObjFalse;
  2743.     }
  2744.     name = GetString(var);
  2745.  
  2746.     var = GetIntVar("ConnectToProcess", process, SOCKETID);
  2747.     if (!var)
  2748.     {
  2749.         return ObjFalse;
  2750.     }
  2751.     port = GetInt(var);
  2752.  
  2753.     connection = NewRemoteScianConnection(name, port, process);
  2754.     SetConnectionState(connection, CS_NAME_ONLY);
  2755.     }
  2756.     NewControlWindow(process);
  2757.  
  2758.     return ObjTrue;
  2759. }
  2760.  
  2761. #ifdef PROTO
  2762. void DoEnablePublication(void)
  2763. #else
  2764. void DoEnablePublication()
  2765. #endif
  2766. /*Enables publication*/
  2767. {
  2768.     NewLocalDaemonConnection();
  2769. }
  2770.  
  2771. static ObjPtr ReplyConnection(dummy, replyText)
  2772. ObjPtr dummy;
  2773. char *replyText;
  2774. /*Makes a new remote daemon connection to machine replyText*/
  2775. {
  2776.     NewRemoteDaemonConnection(replyText);
  2777. }
  2778.  
  2779. void DoConnectToComputer(void)
  2780. /*Initiates a connection to another computer by asking the user for an
  2781.   address and then trying to connect.*/
  2782. {
  2783.     WinInfoPtr askWindow;
  2784.     char hostName[200];
  2785.  
  2786.     gethostname(hostName, 199);
  2787.     hostName[199] = 0;
  2788.     askWindow = AskUser((WinInfoPtr) NULLOBJ, "Enter the name or the IP address of the computer to connect:",
  2789.          (FuncTyp) ReplyConnection, 
  2790.         lastComputer ? lastComputer : hostName);
  2791.     if (askWindow) SetVar((ObjPtr) askWindow, HELPSTRING,
  2792.     NewString("In order to connect to a computer, you must first enter \
  2793. its internet name (e.g. foo.bar.moo.cow.edu) or its internet address (e.g. \
  2794. 128.182.2.255).  Enter the name or address here and press OK to connect to \
  2795. the computer.  Press Cancel to cancel the connection."));
  2796. }
  2797.  
  2798. #ifdef PROTO
  2799. void CloseConnection(ObjPtr connection)
  2800. #else
  2801. void CloseConnection(connection)
  2802. ObjPtr connection;
  2803. #endif
  2804. {
  2805.     if (OBJTYPE(connection -> flags) == CONNECTION)
  2806.     {
  2807.     ObjPtr var;
  2808.     int connectionKind;
  2809.     int sock;
  2810.  
  2811.     sock = (((ConnectionPtr) connection) -> sock);
  2812.     var = GetIntVar("CleanupConnection", connection, CONNECTIONKIND);
  2813.  
  2814.     connectionKind = GetInt(var);
  2815.  
  2816.     if (connectionKind == CK_LOCAL_DAEMON)
  2817.     {
  2818.         if (sock >= 0)
  2819.         {
  2820.                 /*I am not here*/
  2821.                 sprintf(tempStr, "%s %d\n", ND_UNREG_PROCESS, getpid());
  2822.             writen(sock, tempStr, strlen(tempStr));
  2823.             sleep(1);
  2824.         }
  2825.     }
  2826.  
  2827.     /*Say bye*/
  2828.     if (sock >= 0 && (connectionKind == CK_LOCAL_DAEMON ||
  2829.                connectionKind == CK_REMOTE_DAEMON))
  2830.     {
  2831.         /*Send a close*/
  2832.         sprintf(tempStr, "%s\n", ND_CLOSE);
  2833.         writen(sock, tempStr, strlen(tempStr));
  2834.         sleep(1);
  2835.     }
  2836.  
  2837.     if (sock >= 0)
  2838.     {
  2839.         close(sock);
  2840.     }
  2841.     else if (((ConnectionPtr) connection) -> template >= 0)
  2842.     {
  2843.         close(((ConnectionPtr) connection) -> template);
  2844.     }
  2845.     ((ConnectionPtr) connection) -> sock = -1;
  2846.     ((ConnectionPtr) connection) -> template = -1;
  2847.     }
  2848. }
  2849.  
  2850. ObjPtr CleanupConnection(connection)
  2851. ObjPtr connection;
  2852. /*Clean up a connection*/
  2853. {
  2854.     if (OBJTYPE(connection -> flags) == CONNECTION)
  2855.     {
  2856.     CloseConnection(connection);
  2857.     }
  2858.  
  2859.     return ObjTrue;
  2860. }
  2861.  
  2862. #ifdef MESGSTATS
  2863. #define NUMMESGSTATS 17
  2864.  
  2865. static struct {
  2866.     int inCount;
  2867.     int outCount;
  2868.     char *cmd;
  2869.     char *cmdName;
  2870. } mesgStats[NUMMESGSTATS] = {{0, 0, NO_MESG_OBJECT, "object"},
  2871. /*  2 */           {0, 0, NO_MESG_SEND_OBJECT, "send object"},
  2872. /*  3 */           {0, 0, NO_MESG_DELETE_OBJECT, "delete object"},
  2873. /*  4 */           {0, 0, NO_MESG_MAKEVAR, "makevar"},
  2874. /*  5 */           {0, 0, NO_MESG_DIDMAKEVAR, "did makevar"},
  2875. /*  6 */           {0, 0, NO_MESG_DIDNTMAKEVAR, "didn\'t makevar"},
  2876. /*  7 */           {0, 0, NO_MESG_GETVAR, "get var"},
  2877. /*  8 */           {0, 0, NO_MESG_GETELEMENT, "get element"},
  2878. /*  9 */           {0, 0, NO_MESG_GOTVAR, "got var"},
  2879. /* 10 */           {0, 0, NO_MESG_GOTELEMENT, "got element"},
  2880. /* 11 */           {0, 0, NO_MESG_UPDATEVAR, "update var"},
  2881. /* 12 */           {0, 0, NO_MESG_UPDATEVAR_ID, "update var + id"},
  2882. /* 13 */           {0, 0, NO_MESG_UPDATEVAR_SEND, "update var + send"},
  2883. /* 14 */           {0, 0, NO_MESG_MACHINE_IRIS4D, "machine iris 4d"},
  2884. /* 15 */           {0, 0, NO_MESG_MACHINE_RS6000, "machine rs6000"},
  2885. /* 16 */           {0, 0, NO_MESG_MACHINE_UNKNOWN, "machine unknown"},
  2886. /* 17 */           {0, 0, "OTHR", "other"}};
  2887.  
  2888. #endif
  2889.  
  2890. #ifdef PROTO
  2891. void SendSocketCommandLater(ObjPtr connection, char *command)
  2892. #else
  2893. void SendSocketCommandLater(connection, command)
  2894. ObjPtr connection;
  2895. char *command;
  2896. #endif
  2897. /*Sends command to connection later*/
  2898. {
  2899.     ObjPtr cmdQueue;
  2900.     int i;
  2901.  
  2902.     cmdQueue = GetVar(connection, OUTPUTQUEUE);
  2903.     if (!cmdQueue)
  2904.     {
  2905.     cmdQueue = NewList();
  2906.     }
  2907.  
  2908.     PostfixList(cmdQueue, NewString(command));
  2909.     SetVar(connection, OUTPUTQUEUE, cmdQueue);
  2910.  
  2911. #ifdef MESGSTATS
  2912.     for (i = 0; i < NUMMESGSTATS; ++i)
  2913.     {
  2914.     if (i == NUMMESGSTATS - 1 || CMD(command) == CMD(mesgStats[i].cmd))
  2915.     {
  2916.         ++mesgStats[i].outCount;
  2917.         break;
  2918.     }
  2919.     }
  2920. #endif
  2921. }
  2922.  
  2923. void SendObjectLater(connection, obj)
  2924. ObjPtr connection, obj;
  2925. {
  2926.     ObjPtr cmdQueue, sentList;
  2927.  
  2928.     cmdQueue = GetVar(connection, OUTPUTQUEUE);
  2929.     if (!cmdQueue)
  2930.     {
  2931.     cmdQueue = NewList();
  2932.     }
  2933.  
  2934.     PostfixList(cmdQueue, obj);
  2935.     SetVar(connection, OUTPUTQUEUE, cmdQueue);
  2936.  
  2937. #ifdef NEWSTYLEUPDATES
  2938.     if (!ObjectWasSent(obj, connection))
  2939.     {
  2940.     sentList = GetVar(connection, ALLSENTLIST);
  2941.     if (!sentList || !IsList(sentList))
  2942.     {
  2943.         sentList = NewList();
  2944.     }
  2945.     PrefixList(sentList, obj);
  2946.     SetVar(connection, ALLSENTLIST, sentList);
  2947.     }
  2948.     else
  2949.     {
  2950.     fprintf(stderr, "hmm.. resending something..\n");
  2951.     }
  2952. #endif
  2953. }
  2954.  
  2955. static ObjPtr ShowProcessControls(process, windowName)
  2956. ObjPtr process;
  2957. char *windowName;
  2958. /*Makes a new control window to control a process */
  2959. {
  2960.     WinInfoPtr controlWindow;
  2961.     ObjPtr var;
  2962.     ObjPtr panel;
  2963.     ObjPtr corral;
  2964.     ObjPtr contents;
  2965.     WinInfoPtr dialogExists;
  2966.  
  2967.     dialogExists = DialogExists((WinInfoPtr) process, NewString("Controls"));
  2968.     controlWindow = GetDialog((WinInfoPtr) process, NewString("Controls"), windowName, 
  2969.     PXWINWIDTH, PXWINHEIGHT, SCRWIDTH, SCRHEIGHT, WINUI + WINFIXEDSIZE);
  2970.     
  2971.     if (!dialogExists)
  2972.     {
  2973.     ObjPtr connection, textBox, checkBox, icon, palette, name, button, sw;
  2974.     int l, r, b, t, bw;
  2975.     int left, right, bottom, top;
  2976.     char *s;
  2977.     ObjPtr allObjects;
  2978.     ThingListPtr runner;
  2979.  
  2980.     SetVar((ObjPtr) controlWindow, REPOBJ, process);
  2981.  
  2982.     /*Set help string*/
  2983.     SetVar((ObjPtr) controlWindow, HELPSTRING, NewString("This window \
  2984. shows status and running processes for a remote network connection."));
  2985.  
  2986.     l = 0;
  2987.     r = PXWINWIDTH;
  2988.     b = 0;
  2989.     t = PXWINHEIGHT;
  2990.  
  2991.     /*Add in a panel*/
  2992.     panel = NewPanel(greyPanelClass, 0, PXWINWIDTH, 0, PXWINHEIGHT);
  2993.     if (!panel)
  2994.     {
  2995.         return ObjFalse;
  2996.     }
  2997.     contents = GetVar((ObjPtr) controlWindow, CONTENTS);
  2998.     PrefixList(contents, panel);
  2999.     SetVar(panel, PARENT, (ObjPtr) controlWindow);
  3000.     SetVar(panel, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT +
  3001.                      STICKYBOTTOM + STICKYTOP));
  3002.     contents = GetVar(panel, CONTENTS);
  3003.  
  3004.     /*Make an icon corral*/
  3005.     corral = NewIconCorral(NULLOBJ, l + MINORBORDER, r - MINORBORDER, b + 3 * MINORBORDER + 2 * BUTTONHEIGHT, t - MINORBORDER, BARRIGHT + BARBOTTOM);
  3006.     SetVar(corral, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT +
  3007.                      STICKYBOTTOM + STICKYTOP));
  3008.     SetVar(corral, TOPDOWN, ObjTrue);
  3009.     SetVar((ObjPtr) controlWindow, CORRAL, corral);
  3010.     SetVar(corral, NAME, NewString("Process Objects Corral"));
  3011.     SetVar(corral, HELPSTRING,
  3012.     NewString("This corral contains icons for all the objects available through \
  3013. a process connection.  You can visualize, show the controls of, or modify the datasets by selecting \
  3014. some of them and pressing the buttons at the bottom of the window.  You can delete \
  3015. datasets by choosing Delete from the Object menu.  You can also open new datasets by dragging icons from \
  3016. the file window into this corral."));
  3017.     PrefixList(contents, corral);
  3018.     SetVar(corral, PARENT, panel);
  3019.  
  3020.     /*Drop the objects in it*/
  3021.     allObjects = GetVar(process, ALLADVERTISED);
  3022.     if (!allObjects)
  3023.     {
  3024.         allObjects = NewList();
  3025.         SetVar(process, ALLADVERTISED, allObjects);
  3026.     }
  3027.  
  3028.     runner = LISTOF(allObjects);
  3029.     while (runner)
  3030.     {
  3031.         icon = GetVar(runner -> thing, DEFAULTICON);
  3032.         if (icon)
  3033.         {
  3034.         icon = NewObject(icon, 0L);
  3035.         }
  3036.         else
  3037.         {
  3038.         icon = NewIcon(0, 0,ICONQUESTION, "?");
  3039.         }
  3040.         SetVar(icon, REPOBJ, runner -> thing);
  3041.         SetVar(icon, ICONLOC, NULLOBJ);
  3042.         SetVar(icon, CORRAL, corral);
  3043.         DropIconInCorral(corral, icon);
  3044.         runner = runner -> next;
  3045.     }
  3046.  
  3047.     l += MINORBORDER;
  3048.     r -= MINORBORDER;
  3049.     b += 2 * MINORBORDER + BUTTONHEIGHT;
  3050.     t = b + BUTTONHEIGHT;
  3051.     bw = (r - l - MINORBORDER) / 2;
  3052.  
  3053.     /*Make a visualize button*/
  3054.     button = NewFunctionButton(controlWindow,
  3055.             l, l + bw,
  3056.             b, b + BUTTONHEIGHT, OF_VISUALIZE); 
  3057.     if (button)
  3058.     {
  3059.         SetVar(button, PARENT, panel);
  3060.         SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + STICKYLEFT + FLOATINGRIGHT));
  3061.         PrefixList(contents, button);
  3062.     }
  3063.         
  3064.     /*Make a visualize as... button*/
  3065.     button = NewFunctionButton(controlWindow,
  3066.             r - bw, r,
  3067.             b, b + BUTTONHEIGHT, OF_VISUALIZE_AS); 
  3068.     if (button)
  3069.     {
  3070.         SetVar(button, PARENT, panel);
  3071.         SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + FLOATINGLEFT + STICKYRIGHT));
  3072.         PrefixList(contents, button);
  3073.     }
  3074.  
  3075.     t = b - MINORBORDER;
  3076.     b = t - BUTTONHEIGHT;
  3077.     /*Make a show info button*/
  3078.     button = NewFunctionButton(controlWindow,
  3079.             l, l + bw, 
  3080.             b, b + BUTTONHEIGHT, OF_SHOW_CONTROLS); 
  3081.     if (button)
  3082.     {
  3083.         SetVar(button, PARENT, panel);
  3084.         SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + STICKYLEFT + FLOATINGRIGHT));
  3085.         PrefixList(contents, button);
  3086.     }
  3087.  
  3088.     /*Make a modify button*/
  3089.     button = NewFunctionButton(controlWindow, 
  3090.             r - bw, r,
  3091.             b, b + BUTTONHEIGHT, OF_MODIFY);
  3092.     if (button)
  3093.     {
  3094.         SetVar(button, PARENT, panel);
  3095.         SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + FLOATINGLEFT + STICKYRIGHT));
  3096.         PrefixList(contents, button);
  3097.     }
  3098.     }
  3099.     return ObjTrue;
  3100. }
  3101.  
  3102. static ObjPtr ShowConnectionControls(connection, ownerWindow, windowName)
  3103. ObjPtr connection;
  3104. WinInfoPtr ownerWindow;
  3105. char *windowName;
  3106. /*Makes a new control window to control a connection*/
  3107. {
  3108.     WinInfoPtr controlWindow;
  3109.     ObjPtr var;
  3110.     ObjPtr panel;
  3111.     ObjPtr corral;
  3112.     ObjPtr contents;
  3113.     WinInfoPtr dialogExists;
  3114.     char hostName[200];
  3115.  
  3116.     dialogExists = DialogExists((WinInfoPtr) connection, NewString("Controls"));
  3117.     controlWindow = GetDialog((WinInfoPtr) connection, NewString("Controls"), windowName, 
  3118.     SCWINWIDTH, SCWINHEIGHT, SCRWIDTH, SCRHEIGHT, WINUI + WINFIXEDSIZE);
  3119.     
  3120.     if (!dialogExists)
  3121.     {
  3122.     ObjPtr textBox, checkBox, icon, palette, name, button, sw;
  3123.     int l, r, b, t;
  3124.     int left, right, bottom, top;
  3125.     char *s;
  3126.     SetVar((ObjPtr) controlWindow, REPOBJ, connection);
  3127.  
  3128.     /*Set help string*/
  3129.     SetVar((ObjPtr) controlWindow, HELPSTRING, NewString("This window \
  3130. shows status and running processes for a remote network connection."));
  3131.  
  3132.     l = 0;
  3133.     r = SCWINWIDTH;
  3134.     b = 0;
  3135.     t = SCWINHEIGHT;
  3136.  
  3137.     /*Add in a panel*/
  3138.     panel = NewPanel(greyPanelClass, 0, SCWINWIDTH, 0, SCWINHEIGHT);
  3139.     if (!panel)
  3140.     {
  3141.         return ObjFalse;
  3142.     }
  3143.     contents = GetVar((ObjPtr) controlWindow, CONTENTS);
  3144.     PrefixList(contents, panel);
  3145.     SetVar(panel, PARENT, (ObjPtr) controlWindow);
  3146.     SetVar(panel, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT +
  3147.                      STICKYBOTTOM + STICKYTOP));
  3148.  
  3149.     contents = GetVar(panel, CONTENTS);
  3150.     
  3151.     /*Add in the icons*/
  3152.  
  3153.     left = l + MAJORBORDER;
  3154.     right = l + MAJORBORDER + SCGRAPHICWIDTH;
  3155.     top = t - MAJORBORDER;
  3156.     bottom = top - ICONSIZE;
  3157.  
  3158.     gethostname(hostName, 199);
  3159.     hostName[199] = 0;
  3160.     icon = NewIcon(left + ICONSIZE / 2, top - ICONSIZE / 2, ICONWORKSTATION,
  3161.         "SciAn");
  3162.     PrefixList(contents, icon);
  3163.     SetVar(icon, PARENT, (ObjPtr) controlWindow);
  3164.     SetVar(icon, STICKINESS, NewInt(STICKYLEFT + STICKYTOP));
  3165.     SetVar(icon, HELPSTRING, NewString("This icon represents the workstation running \
  3166. SciAn that you are using right now.  It's part of a graphic that shows that the window \
  3167. is a network connection window.  Other than that, it doesn't really do anything."));
  3168.  
  3169.     icon = NewIcon(right - ICONSIZE / 2, top - ICONSIZE / 2, ICONCOMPUTER,
  3170.         "Host");
  3171.     PrefixList(contents, icon);
  3172.     SetVar(icon, PARENT, (ObjPtr) controlWindow);
  3173.     SetVar(icon, STICKINESS, NewInt(STICKYLEFT + STICKYTOP));
  3174.     SetVar(icon, HELPSTRING, NewString("This icon represents the remote computer \
  3175. that you are connected to.  It's part of a graphic that shows that the window \
  3176. is a network connection window.  Other than that, it doesn't really do anything."));
  3177.  
  3178.     /*Put a switch between the icons*/
  3179.     sw = NewFlowLine(left + ICONSIZE + MINORBORDER, right - ICONSIZE - MINORBORDER, bottom, top, "Graphic Flow Line");
  3180.     PrefixList(contents, sw);
  3181.     SetVar(sw, PARENT, (ObjPtr) controlWindow);
  3182.     SetVar(sw, STICKINESS, NewInt(STICKYLEFT + STICKYTOP));
  3183.  
  3184.     /*Add the info description*/
  3185.     left = l + 2 * MAJORBORDER + SCGRAPHICWIDTH;
  3186.     right = r - MINORBORDER;
  3187.     top = t - MINORBORDER;
  3188.     bottom = top - SCTEXTHEIGHT;
  3189.  
  3190.     s = tempStr;
  3191.     sprintf(s, "Network Connection\nHost: ");
  3192.     while (*s) ++s;
  3193.  
  3194.     var = GetVar(connection, NAME);
  3195.     if (var)
  3196.     {
  3197.         sprintf(s, "%s\n", GetString(var));
  3198.     }
  3199.     else
  3200.     {
  3201.         sprintf(s, "Unknown\n");
  3202.     }
  3203.     while (*s) ++s;
  3204.  
  3205.     /*Create the text box*/
  3206.     textBox = NewTextBox(left, right, 
  3207.              bottom, top,
  3208.              0, "Info Text", tempStr);
  3209.     PrefixList(contents, textBox);
  3210.     SetVar(textBox, PARENT, panel);
  3211.     SetVar(textBox, TEXTFONT, NewString(SCFONT));
  3212.     SetVar(textBox, TEXTSIZE, NewInt(SCFONTSIZE));
  3213.     SetVar(textBox, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT + STICKYTOP));
  3214.  
  3215.     /*Make an icon corral*/
  3216.     top = bottom - MAJORBORDER;
  3217.     left = MINORBORDER;
  3218.     right = r - MINORBORDER;
  3219.     bottom = b + 2 * MINORBORDER + BUTTONHEIGHT;
  3220.     corral = NewIconCorral(NULLOBJ, left, right, bottom, top, BARRIGHT + BARBOTTOM);
  3221.     SetVar(corral, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT +
  3222.                      STICKYBOTTOM + STICKYTOP));
  3223.     SetVar(corral, TOPDOWN, ObjTrue);
  3224.     SetVar((ObjPtr) controlWindow, CORRAL, corral);
  3225.     SetVar(corral, NAME, NewString("Processes Corral"));
  3226.     SetVar(corral, HELPSTRING,
  3227.         NewString("This corral contains icons for all the processes running on the \
  3228. host machine.  You can show the controls of a process by selecting it and pressing \
  3229. the Show Controls button."));
  3230.     PrefixList(contents, corral);
  3231.     SetVar(corral, PARENT, panel);
  3232.  
  3233.     bottom = b + MINORBORDER;
  3234.     top = bottom + BUTTONHEIGHT;
  3235.     right = (l + r) / 2;
  3236.  
  3237.     /*Make a show controls button*/
  3238.     button = NewFunctionButton(controlWindow,
  3239.         left, right, bottom, top, OF_CONNECT_TO_PROCESS); 
  3240.     if (button)
  3241.     {
  3242.         SetVar(button, PARENT, panel);
  3243.         SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + STICKYLEFT + FLOATINGRIGHT));
  3244.         PrefixList(contents, button);
  3245.     }
  3246.     }
  3247.  
  3248.     return (ObjPtr) controlWindow;
  3249. }
  3250. #endif
  3251.  
  3252. #ifdef SOCKETS
  3253. #ifdef PARANOID
  3254. int WFNOVCount = 0;
  3255. #endif
  3256. #endif
  3257.  
  3258. /* any vars of object that are gotten in here or in underlying calls **MUST**
  3259.  * have been set locally!
  3260.  */
  3261. Bool WaitForNetObjectElement(object, offset)
  3262. ObjPtr object;
  3263. unsigned long offset;
  3264. {
  3265. #ifdef SOCKETS
  3266.     ObjPtr connection, process, allObjects;
  3267.     ThingListPtr thing;
  3268.     ObjPtr oldThing;
  3269.     double time;
  3270.     Bool wasNetStub;
  3271.  
  3272. #ifdef DEBUG
  3273. fprintf(stderr, "waiting for object %lx, element %ld\n", object, offset);
  3274. #endif
  3275.  
  3276. #ifdef PARANOID
  3277.     if (++WFNOVCount > 1)
  3278.     {
  3279.     ReportError("WaitForNetObjectElement", "HEY! Multiple calls to WaitForNetObject* are active! Very Bad!");
  3280.     }
  3281. #endif
  3282.  
  3283.     if (!IsObjArray(object))
  3284.     {
  3285.     ReportError("WaitForNetObjectElement", "not an ObjArray");
  3286.     }
  3287.     else if (!(connection = GetVar(object, OWNERCONNECTION)))
  3288.     {
  3289.     ReportError("WaitForNetObjectElement", "network object has no OWNERCONNECTION");
  3290.     }
  3291.     else if(!(process = GetVar(connection, OWNERPROCESS)))
  3292.     {
  3293.     ReportError("WaitForNetObjectElement", "network object has no OWNERPROCESS");
  3294.     }
  3295.     else
  3296.     {
  3297.     ObjPtr *elements;
  3298.  
  3299.     elements = (ObjPtr *) ELEMENTS(object);
  3300.  
  3301. /* Always send it for now */
  3302.         /* ReportError("WaitForNetObjectElement", "Object not already waiting!"); */
  3303.         SendGetElementMessage(object, offset);
  3304.  
  3305.     time = WallClock();
  3306.     /* wasNetStub = NETSTUBFLAG == varNode -> remoteNetID; */
  3307.     wasNetStub = true;
  3308.     while (WallClock() < time + LONG_TIMEOUT && IsNetworkIDWaiting(process, (unsigned long) elements[offset]))
  3309.     {
  3310.         while (IdleAllConnections())
  3311.         ;
  3312.         if (wasNetStub && (elements[offset] != (ObjPtr) NETSTUBFLAG))
  3313.         {
  3314.         /* got results of GETVAR message, send get object msg if we don't already have it */
  3315.         if (elements[offset] && !FindRemoteObject(process, (unsigned long) elements[offset], false))
  3316.         {
  3317.             SendSendObjectMessage(connection, (unsigned long) elements[offset]);
  3318.             wasNetStub = false;
  3319.         }
  3320.         }
  3321.     }
  3322.     if (WallClock() >= time + LONG_TIMEOUT)
  3323.     {
  3324.         sprintf(tempStr, "timed out waiting for element %ld\n", offset);
  3325.         ReportError("WaitForNetObjectElement", tempStr);
  3326.         /* if (elements[offset] == (ObjPtr) NETSTUBFLAG) */
  3327.         elements[offset] == NULLOBJ;
  3328. /* exit(0); */
  3329.     }
  3330.     else
  3331.     {
  3332. #ifdef PARANOID
  3333.         --WFNOVCount;
  3334. #endif
  3335.  
  3336. #ifdef DEBUG
  3337.         fprintf(stderr, "done waiting for object %lx, element %ld (remoteNetID %ld), trying to find it now\n", object, offset, (unsigned long) elements[offset]);
  3338. #endif
  3339.         elements[offset] = FindRemoteObject(process, (unsigned long) elements[offset], false);
  3340.         return true;
  3341.     }
  3342.     }
  3343.  
  3344. #ifdef DEBUG
  3345.     fprintf(stderr, "Abnormal exit waiting for object %lx, offset %ld\n", object, offset);
  3346. #endif
  3347.  
  3348. #ifdef PARANOID
  3349.     --WFNOVCount;
  3350. #endif
  3351.  
  3352. #endif
  3353.     return false;
  3354. }
  3355.  
  3356. /* any vars of object that are gotten in here or in underlying calls **MUST**
  3357.  * have been set locally!
  3358.  */
  3359. Bool WaitForNetObjectVar(object, varNode)
  3360. ObjPtr object;
  3361. VarsPtr varNode;
  3362. {
  3363. #ifdef SOCKETS
  3364.     ObjPtr connection, process, allObjects;
  3365.     ThingListPtr thing;
  3366.     ObjPtr oldThing;
  3367.     double time;
  3368.     Bool wasNetStub;
  3369.  
  3370. #ifdef DEBUG
  3371. fprintf(stderr, "waiting for object %lx, var %ld (remoteNetID %ld)\n", object, varNode -> name, varNode -> remoteNetID);
  3372. #endif
  3373.  
  3374. #ifdef PARANOID
  3375.     if (++WFNOVCount > 1)
  3376.     {
  3377.     ReportError("WaitForNetObjectVar", "HEY! Multiple calls are active! Very Bad!");
  3378.     }
  3379. #endif
  3380.  
  3381.     connection = GetVar(object, OWNERCONNECTION);
  3382.     if (!(connection = GetVar(object, OWNERCONNECTION)))
  3383.     {
  3384.     ReportError("WaitForNetObjectVar", "network object has no OWNERCONNECTION");
  3385.     }
  3386.     else if(!(process = GetVar(connection, OWNERPROCESS)))
  3387.     {
  3388.     ReportError("WaitForNetObjectVar", "network object has no OWNERPROCESS");
  3389.     }
  3390.     else if (!varNode)
  3391.     {
  3392.     ReportError("WaitForNetObjectVar", "waiting for nothing!");
  3393.     }
  3394.     else
  3395.     {
  3396.     int firstTime = 1;
  3397.  
  3398.     if (!IsNetworkIDWaiting(process, varNode -> remoteNetID))
  3399.     {
  3400.         ReportError("WaitForNetObjectVar", "Object not already waiting!");
  3401.         SendGetVarMessage(object, varNode -> name);
  3402.     }
  3403.  
  3404.     time = WallClock();
  3405.     wasNetStub = NETSTUBFLAG == varNode -> remoteNetID;
  3406.     while (!IsDefunct(object) && WallClock() < time + LONG_TIMEOUT && IsNetworkIDWaiting(process, varNode -> remoteNetID))
  3407.     {
  3408.         varNode = GetVarNode(object, varNode -> name);
  3409.         while (IdleAllConnections())
  3410.         ;
  3411.         if (wasNetStub && varNode -> remoteNetID != NETSTUBFLAG)
  3412.         {
  3413.         /* got results of GETVAR message, send get object msg if we don't already have it */
  3414.         if (varNode -> remoteNetID && !FindRemoteObject(process, varNode -> remoteNetID, false))
  3415.         {
  3416.             SendSendObjectMessage(connection, varNode -> remoteNetID);
  3417.             wasNetStub = false;
  3418.         }
  3419.         }
  3420.     }
  3421.  
  3422.     if (IsDefunct(object))
  3423.     {
  3424.         sprintf(tempStr, "target %lx was marked ISDEFUNCT while waiting for %ld", object, varNode -> name);
  3425.         ReportError("WaitForNetObjectVar", tempStr);
  3426.     }
  3427.     else if (WallClock() >= time + LONG_TIMEOUT)
  3428.     {
  3429.         sprintf(tempStr, "timed out waiting for var %ld", varNode -> name);
  3430.         ReportError("WaitForNetObjectVar", tempStr);
  3431. /* exit(0); */
  3432.     }
  3433.     else
  3434.     {
  3435. #ifdef PARANOID
  3436.         --WFNOVCount;
  3437. #endif
  3438.  
  3439. #ifdef DEBUG
  3440.         fprintf(stderr, "done waiting for object %lx, var %ld (remoteNetID %ld)\n", object, varNode -> name, varNode -> remoteNetID);
  3441. #endif
  3442.  
  3443.         return true;
  3444.     }
  3445.     }
  3446.  
  3447. #ifdef DEBUG
  3448.     fprintf(stderr, "Abnormal exit waiting for object %lx, var %ld (remoteNetID %ld)\n", object, varNode -> name, varNode -> remoteNetID);
  3449. #endif
  3450.  
  3451. #ifdef PARANOID
  3452.     --WFNOVCount;
  3453. #endif
  3454.  
  3455. #endif
  3456.     return false;
  3457. }
  3458.  
  3459. Bool WaitForNetObject(ObjPtr connection, unsigned long netid)
  3460. {
  3461. #ifdef SOCKETS
  3462. ObjPtr process;
  3463. double time;
  3464.  
  3465. #ifdef DEBUG
  3466. fprintf(stderr, "waiting for remoteNetID %ld\n", netid);
  3467. #endif
  3468.  
  3469. #ifdef PARANOID
  3470.     if (++WFNOVCount > 1)
  3471.     {
  3472.     ReportError("WaitForNetObject", "multiple calls are active! Very Bad!");
  3473.     }
  3474.  
  3475.     if (!netid)
  3476.     {
  3477.     ReportError("WaitForNetObject", "waiting for netid 0!");
  3478.     }
  3479. #endif
  3480.  
  3481.     process = GetVar(connection, OWNERPROCESS);
  3482.  
  3483.     if (!process)
  3484.     {
  3485.     ReportError("WaitForNetObject", "connection has no OWNERPROCESS");
  3486.     }
  3487.     else
  3488.     {
  3489.     if (!IsNetworkIDWaiting(process, netid))
  3490.     {
  3491.         ReportError("WaitForNetObject", "Object not already waiting!");
  3492.         SendSendObjectMessage(connection, netid);
  3493.     }
  3494.  
  3495.     time = WallClock();
  3496.     while (WallClock() < time + LONG_TIMEOUT && IsNetworkIDWaiting(process, netid))
  3497.     {
  3498.         while (IdleAllConnections())
  3499.         ;
  3500.     }
  3501.     if (WallClock() >= time + LONG_TIMEOUT)
  3502.     {
  3503.         sprintf(tempStr, "timed out waiting for object, netid %ld\n", netid);
  3504.         ReportError("WaitForNetObject", tempStr);
  3505. /* exit(0); */
  3506.     }
  3507.     else
  3508.     {
  3509. #ifdef PARANOID
  3510.         --WFNOVCount;
  3511. #endif
  3512.  
  3513. #ifdef DEBUG
  3514. fprintf(stderr, "done waiting for remoteNetID %ld\n", netid);
  3515. #endif
  3516.         return true;
  3517.     }
  3518.     }
  3519. #ifdef PARANOID
  3520.     --WFNOVCount;
  3521. #endif
  3522.  
  3523. #ifdef DEBUG
  3524. fprintf(stderr, "Abnormal exit waiting for remoteNetID %ld\n", netid);
  3525. #endif
  3526.  
  3527.  
  3528. #endif
  3529.     return false;
  3530. }
  3531.  
  3532. void InitSockets(void)
  3533. /*Initializes the socket system*/
  3534. {
  3535. #ifdef SOCKETS
  3536.     advertiseableClass = NewObject(NULLOBJ, 0L);
  3537.     SetMethod(advertiseableClass, ADVERTISE, AdvertiseObject);
  3538.     SetMethod(advertiseableClass, UNADVERTISE, UnadvertiseObject);
  3539.     allAdvertised = NewList();
  3540.     AddToReferenceList(advertiseableClass);
  3541.     AddToReferenceList(allAdvertised);
  3542.  
  3543.     connectionClass = NewObject(NULLOBJ, 0L);
  3544.     AddToReferenceList(connectionClass);
  3545.     SetMethod(connectionClass, TIMEOUT, TimeoutConnection);
  3546.     SetMethod(connectionClass, CLEANUP, CleanupConnection);
  3547.     SetMethod(connectionClass, NEWCTLWINDOW, ShowConnectionControls);
  3548.  
  3549.     /*Make class for processes*/
  3550.     processClass = NewObject(NULLOBJ, 0L);
  3551.     AddToReferenceList(processClass);
  3552.     SetMethod(processClass, NEWCTLWINDOW, ShowProcessControls);
  3553.     SetMethod(processClass, CONNECTTOPROCESS, ConnectToProcess);
  3554.  
  3555.     /*Make icons for process*/
  3556.     processIcon = NewIcon(10, 10, ICONPROCESS, "Process");
  3557.     AddToReferenceList(processIcon);
  3558.  
  3559.     allConnections = NewList();
  3560.     AddToReferenceList(allConnections);
  3561. #endif
  3562. }
  3563.  
  3564. void KillSockets(void)
  3565. /*Kills the socket system*/
  3566. {
  3567. #ifdef SOCKETS
  3568.     int i;
  3569.  
  3570.     RemoveFromReferenceList(allConnections);
  3571.     RemoveFromReferenceList(processIcon);
  3572.     RemoveFromReferenceList(processClass);
  3573.     RemoveFromReferenceList(connectionClass);
  3574.     if (lastComputer)
  3575.     {
  3576.     Free(lastComputer);
  3577.     lastComputer = 0;
  3578.     }
  3579.     RemoveFromReferenceList(allAdvertised);
  3580.     RemoveFromReferenceList(advertiseableClass);
  3581.  
  3582. #ifdef MESGSTATS
  3583.     for (i = 0; i < NUMMESGSTATS; ++i)
  3584.     {
  3585.     fprintf(stderr, "%5d %s\n",mesgStats[i].outCount,mesgStats[i].cmdName);
  3586.     }
  3587. #endif
  3588. #endif
  3589. }
  3590.